首页 文章

如何使用Jasmine和/或Sinon正确地测试jQuery的.ajax()承诺?

提问于
浏览
55

我有一个相当简单的函数,它返回一个jQuery .ajax()的承诺:

CLAW.controls.validateLocation = function(val, $inputEl) {
    return $.ajax({
        url: locationServiceUrl + 'ValidateLocation/',
        data: {
            'locationName': val
        },
        beforeSend: function() {
            $inputEl.addClass('busy');
        }
    }).done(function(result) {
        // some success clauses
    }).fail(function(result) {
        // some failure clauses
    }).always(function() {
        // some always clauses
    });
}

在大多数情况下,这个新的promises接口就像一个梦想,并在使用jQuery的.ajax()时很好地消除了回调金字塔 . 但是,我不能为我的生活弄清楚如何使用Jasmine和/或Sinon正确测试这些承诺:

  • 所有Sinon的文档都假设您使用的是旧式回调;我没有看到如何将它与promises / deferred一起使用的单个示例

  • 当试图使用Jasmine或Sinon Spy 来监视$ .ajax时, Spy 实际上会覆盖承诺,因此它的 donefailalways 条款不再存在于ajax函数中,所以承诺永远不会解决并抛出一个而是错误

我真的很喜欢一个或两个如何用上述测试库测试这些新的jQuery .ajax()promises的例子 . 我已经相当强烈地搜索了'网,并没有真正挖掘任何东西这样做 . 我找到的一个资源是使用Jasmine.ajax提到的,但我想尽可能避免这种情况,因为Sinon提供了大部分开箱即用的相同功能 .

4 回答

  • 0

    实际上并不复杂 . 只需返回一个承诺并根据您的情况解决它 .

    例如:

    spyOn($, 'ajax').andCallFake(function (req) {
        var d = $.Deferred();
        d.resolve(data_you_expect);
        return d.promise();
    });
    

    为了成功,或

    spyOn($, 'ajax').andCallFake(function (req) {
        var d = $.Deferred();
        d.reject(fail_result);
        return d.promise();
    });
    

    因为失败 .

    对于Jasmine 2.0,语法略有改变:

    spyOn($, 'ajax').and.callFake(function (req) {});
    

    Jasmine 2.0中不存在.andCallFake()方法

  • 0

    沿着这些线/与sinon和jQuery延迟的东西

    ajaxStub = sinon.stub($, "ajax");
    
    function okResponse() {
      var d = $.Deferred();
      d.resolve( { username: "testuser", userid: "userid", success: true } );
      return d.promise();
    };
    
    function errorResponse() {
     var d = $.Deferred();
     d.reject({},{},"could not complete");
     return d.promise();
    };
    
    ajaxStub.returns(okResponse());
    ajaxStub.returns(errorResponse());
    
  • 16

    这是一个简单的方法,只需javascript .

    quoteSnapshots: function (symbol, streamId) {
                    var FakeDeferred = function () {
                        this.error = function (fn) {
                            if (symbol.toLowerCase() === 'bad-symbol') {
                                fn({Error: 'test'});
                            }
                            return this;
                        };
                        this.data = function (fn) {
                            if (symbol.toLowerCase() !== 'bad-symbol') {
                                fn({});
                            }
                            return this;
                        };
                    };
    
                    return new FakeDeferred();
                }
    

    每个回调中的if语句都是我在测试中用来驱动成功或错误执行的 .

  • 106

    如果您使用 .complete() 之类的东西,@ ggozad给出的解决方案将无效 .

    但是,讽刺的是,茉莉花做了一个插件来做到这一点:http://jasmine.github.io/2.0/ajax.html

    beforeEach(function() {
      jasmine.Ajax.install();
    });
    
    afterEach(function() {
      jasmine.Ajax.uninstall();
    });
    
    //in your tests
    expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url');
    

相关问题