如何正确使用Jasmine和/或Sinonunit testingjQuery的.ajax()承诺?

我有一个相当简单的函数,它返回一个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 }); } 

在大多数情况下,这个新的承诺接口像梦一样工作,并消除使用jQuery的.ajax()的callback金字塔是伟大的。 然而,我不能为了我的生活弄清楚如何用Jasmine和/或Sinon来正确地testing这些承诺:

  1. Sinon的所有文档都假设你正在使用旧式的callback, 我没有看到一个如何与promise / deferreds一起使用的例子

  2. 当试图用Jasmine或Sinon间谍来监视$ .ajax时,间谍正在有效地覆盖承诺,所以它的donefailalways子句不再存在于ajax函数中,所以承诺永远不会解决和抛出一个错误代替

我真的只是喜欢一个或两个如何testing这些新的jQuery .ajax()承诺与上述testing库。 我对networking的search力度相当强,而且还没有真正挖掘过这些东西。 我使用Jasmine.ajax提到的一个资源,但是如果可能的话,我想尽量避免使用Sinon提供的大部分相同的function。

实际上并不那么复杂。 根据您的情况返回承诺并解决问题就足够了。

例如:

 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()方法

一些沿着这些线/与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()); 

这是一个简单的方法与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(); } 

每个callback中的if语句都是我在testing中用来驱动成功或错误执行的东西。

如果使用像.complete()这样的东西,@ggozad给出的解决scheme将不起作用。

但是,万岁,茉莉花做了一个插件来做到这一点: 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');