We actually ran into the same problem, trying to test Deferred objects that represent AJAXed template scripts for on-the-fly templating. Our testing solution involves using the Jasmine-Ajax library in conjunction with Jasmine itself.
So probably it will be something like this:
describe('When Submit button handler fired', function () {
jasmine.Ajax.useMock();
describe('if the message is empty', function () {
beforeEach(function() {
spyOn(backendController, 'submitForm').andCallThrough();
// replace with wherever your callbacks are defined
spyOn(this, 'onSuccess');
spyOn(this, 'onFailure');
this.view.$el.find('#message').text('');
this.view.$el.find('form').submit();
});
it('backendController.submitForm and fail Deferred Object should be called', function () {
expect(backendController.submitForm).toHaveBeenCalledWith('');
mostRecentAjaxRequest().response({
status: 500, // or whatever response code you want
responseText: ''
});
expect( this.onSuccess ).not.toHaveBeenCalled();
expect( this.onFailure ).toHaveBeenCalled();
});
});
Another thing, if you can, try to break up the functionality so you're not testing the entire DOM-to-response-callback path in one test. If you're granular enough, you can actually test asynchronous Deferred resolutions by using Deferred objects themselves inside your tests!
The key is to actually use Deferred objects within your tests themselves, so that the scope of the expect
call is still within your it
function block.
describe('loadTemplate', function() {
it('passes back the response text', function() {
jasmine.Ajax.mock();
loadTemplate('template-request').done(function(response) {
expect(response).toBe('foobar');
});
mostRecentAjaxRequest().response({ status:200, responseText:'foobar' });
});
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…