如何使用jasmine测试已完成和失败的延迟对象

Lor*_*ard 28 javascript jquery post jasmine

这是关于javascript提交请求的代码(1).
以下是使用jasmine(2)模拟ajax请求的测试.

我想模拟服务器行为.有任何想法吗?
有关详细信息,请参阅(1)和(2)中的注释.

PS:
实际上在两种情况下都会调用fakeFunction的done和fail Deferred Object.


(1)

submitForm: function () {
     // the server execute fail only if message.val() is empty
     // and I would like to mock this behaviour in (2)
     backendController.submitForm(message.val()).done(this.onSuccess).fail(this.onError);
},

backendController.submitForm = function (message) {
    return $.ajax({
        url: 'some url',
        type: 'POST',
        dataType: 'json',
        data: {
            message: message
        }
    }).done(function () {
        //some code;
    });
};
Run Code Online (Sandbox Code Playgroud)

(2)

describe('When Submit button handler fired', function () {
    var submitFormSpy,
        fakeFunction = function () {
            this.done = function () {
                return this;
            };
            this.fail = function () {
                return this;
            };
            return this;
        };

    beforeEach(function () {
        submitFormSpy = spyOn(backendController, 'submitForm').andCallFake(fakeFunction);
    });

    describe('if the message is empty', function () {
        beforeEach(function () {
            this.view.$el.find('#message').text('');
            this.view.$el.find('form').submit();
        });
        it('backendController.submitForm and fail Deferred Object should be called', function () {
            expect(submitFormSpy).toHaveBeenCalled();
            // how should I test that fail Deferred Object is called?
        });
    });

    describe('if the message is not empty', function () {
        beforeEach(function () {
            this.view.$el.find('#message').text('some text');
            this.view.$el.find('form').submit();
        });
        it('backendController.submitForm should be called and the fail Deferred Object should be not called', function () {
            expect(submitFormSpy).toHaveBeenCalled();
            // how should I test that fail Deferred Object is not called?
        });
    });

});
Run Code Online (Sandbox Code Playgroud)

Ain*_*aer 25

我们实际上遇到了同样的问题,试图测试代表AJAXed模板脚本的Deferred对象以进行实时模板化.我们的测试解决方案涉及将Jasmine-Ajax库与Jasmine本身结合使用.

所以可能会是这样的:

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();
    });
});
Run Code Online (Sandbox Code Playgroud)

另一件事,如果可以的话,尝试分解功能,这样你就不会在一次测试中测试整个DOM-to-response-callback路径.如果你足够精细,你可以通过在测试中使用Deferred对象来实际测试异步延迟分辨率!

关键是在测试中实际使用Deferred对象,这样expect调用的范围仍然在你的it功能块中.

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' });
  });
});
Run Code Online (Sandbox Code Playgroud)


Ton*_*ony 14

以下是我设法做到的方法.

本质上,$ .ajax对象返回一个Deferred对象,因此您可以监视$ .ajax并返回Deferred,然后手动触发它以在JavaScript中运行.done()代码

Index.prototype.sendPositions = function() {
  var me = this;
  $.ajax({
    ...
  }).done(function(data, textStatus, jqXHR) {
    me.reload();
  }).fail(function(jqXHR, textStatus, errorThrown) {
    console.log(errorThrown);
  });
};
Run Code Online (Sandbox Code Playgroud)

测试

it("should reload the page after a successful ajax call", function(){
  var deferred = new jQuery.Deferred();
  spyOn($, 'ajax').andReturn(deferred);
  spyOn(indexPage, 'reload');
  indexPage.sendPositions();
  deferred.resolve('test');
  expect(indexPage.reload).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)

  • PS监视失败,而不是调用deferred.resolve()调用deferred.reject() (2认同)