admin管理员组

文章数量:1391951

The following two ways of implementing an ajaxRequest (1) (2) should be equivalent.
Having said that:

  1. Why does the unit test (3) that verifies the callback was executed, succeeds in (1) and fails in (2)?
  2. How should I rewrite the test (3) to spy on the success callback in (2)?
  3. If I try to stub jQuery.ajax using sinon and the code (2) I get an error. How should I fix it?

Please, see the ments in code (3) for more details.


(1)

ajaxRequest: function (message, callback) {
    return $.ajax({
        url: backendRouter.generate('feedback_send'),
        type: 'POST',
        dataType: 'json',
        data: {
            message: message
        },
        success: callback
    });
}

(2)

ajaxRequest: function (message, callback) {
    return $.ajax({
        url: backendRouter.generate('feedback_send'),
        type: 'POST',
        dataType: 'json',
        data: {
            message: message
        }
    }).success(callback);
}

(3)

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    }); // If I use the code (2) I get the following error
        // TypeError: Object #<Object> has no method 'success'
    var callback = jasmine.createSpy();
    ajaxRequest('some message', callback);
    expect(callback).toHaveBeenCalled();
});

(4)

it("makes a GET request for todo items", function () {
    sinon.stub(jQuery, 'ajax');
    backendController.ajaxRequest('some message', sinon.spy()); 
    // Cannot call method 'success' of undefined
});

The following two ways of implementing an ajaxRequest (1) (2) should be equivalent.
Having said that:

  1. Why does the unit test (3) that verifies the callback was executed, succeeds in (1) and fails in (2)?
  2. How should I rewrite the test (3) to spy on the success callback in (2)?
  3. If I try to stub jQuery.ajax using sinon and the code (2) I get an error. How should I fix it?

Please, see the ments in code (3) for more details.


(1)

ajaxRequest: function (message, callback) {
    return $.ajax({
        url: backendRouter.generate('feedback_send'),
        type: 'POST',
        dataType: 'json',
        data: {
            message: message
        },
        success: callback
    });
}

(2)

ajaxRequest: function (message, callback) {
    return $.ajax({
        url: backendRouter.generate('feedback_send'),
        type: 'POST',
        dataType: 'json',
        data: {
            message: message
        }
    }).success(callback);
}

(3)

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    }); // If I use the code (2) I get the following error
        // TypeError: Object #<Object> has no method 'success'
    var callback = jasmine.createSpy();
    ajaxRequest('some message', callback);
    expect(callback).toHaveBeenCalled();
});

(4)

it("makes a GET request for todo items", function () {
    sinon.stub(jQuery, 'ajax');
    backendController.ajaxRequest('some message', sinon.spy()); 
    // Cannot call method 'success' of undefined
});
Share Improve this question edited Aug 24, 2012 at 9:21 Lorraine Bernard asked Aug 23, 2012 at 8:50 Lorraine BernardLorraine Bernard 13.5k23 gold badges85 silver badges138 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

Here's a walkthrough:

If you use the code in number 2, you are invoking the ajax function on jquery:

return $.ajax({
  url: backendRouter.generate('feedback_send'),
  type: 'POST',
  dataType: 'json',
  data: {
    message: message
  }
...

after calling this function with those parameters, jQuery returns a jqHR that happens to have a success function defined. That success function is then invoked:

...
}).success(callback);

All is well so far until your jasmine test spies on the ajax function. The same options you used to invoke $.ajax are passed to this new spy.

// this is the value of the options parameter
{
    url: backendRouter.generate('feedback_send'),
    type: 'POST',
    dataType: 'json',
    data: {
        message: message
    }
}

When this object is passed, your fake function actually attempts to call options.success, which does not exist! Hence the error.

There is a jquery plugin that uses sinonjs with qunit and provides a much easier way to write ajax tests and get expected results.

Take a look at jqueryspy

本文标签: javascriptHow to spy jQuery AJAX requestStack Overflow