如何使用 Jasmine 和/或 Sinon 正确地对 jQuery 的 .ajax() 承诺进行单元测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13148356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly unit test jQuery's .ajax() promises using Jasmine and/or Sinon?
提问by J. Ky Marsh
I've got a fairly straightforward function which returns a jQuery .ajax() promise as such:
我有一个相当简单的函数,它返回一个 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
});
}
For the most part, this new promises interface works like a dream, and eliminating callback pyramids when using jQuery's .ajax() is great. However, I cannot for the life of me figure out how to properly test these promises using Jasmine and/or Sinon:
在大多数情况下,这个新的 promises 接口就像梦一样工作,并且在使用 jQuery 的 .ajax() 时消除回调金字塔很棒。但是,我终生无法弄清楚如何使用 Jasmine 和/或 Sinon 正确测试这些承诺:
All of Sinon's documentation assumes you're using old-school callbacks; I don't see a single example of how to use it with promises/deferreds
When attempting to use a Jasmine or Sinon spy to spy on $.ajax, the spy is effectively overwriting the promise, so its
done
,fail
, andalways
clauses no longer exist on the ajax function, so the promise never resolves and tosses an error instead
Sinon 的所有文档都假设您使用的是老式回调;我没有看到一个关于如何将它与 promises/deferreds 一起使用的示例
当尝试使用茉莉花或兴农间谍刺探$阿贾克斯,间谍有效覆盖的承诺,所以其
done
,fail
和always
条款不再对AJAX功能的存在,因此承诺永不解析和扔一个错误,而不是
I'd really just love an example or two of how to test these new jQuery .ajax() promises with the aforementioned testing libs. I've scoured the 'net fairly intensely and haven't really dredged up anything on doing so. The one resource I did find mentioned using Jasmine.ajax, but I'd like to avoid that if possible, seeing as Sinon provides most of the same capabilities out-of-the-box.
我真的很喜欢一两个示例,说明如何使用上述测试库测试这些新的 jQuery .ajax() 承诺。我已经相当认真地搜索了“网”,但并没有真正挖掘出任何东西。我确实找到了使用 Jasmine.ajax 提到的一种资源,但如果可能的话,我想避免这种情况,因为 Sinon 提供了大多数开箱即用的相同功能。
回答by ggozad
It is not that complex actually. It suffices to return a promise and resolve it according to your case.
其实没那么复杂。根据您的情况返回承诺并解决它就足够了。
For example:
例如:
spyOn($, 'ajax').andCallFake(function (req) {
var d = $.Deferred();
d.resolve(data_you_expect);
return d.promise();
});
for a success, or
为了成功,或
spyOn($, 'ajax').andCallFake(function (req) {
var d = $.Deferred();
d.reject(fail_result);
return d.promise();
});
for a failure.
对于失败。
For Jasmine 2.0 the syntax has changed slightly:
对于 Jasmine 2.0,语法略有变化:
spyOn($, 'ajax').and.callFake(function (req) {});
the method .andCallFake() does not exist in Jasmine 2.0
方法 .andCallFake() 在 Jasmine 2.0 中不存在
回答by yxa
something along these lines / with sinon and jQuery deferreds
沿着这些路线 / 使用 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());
回答by sam
Here's a simpler approach with just javascript.
这是一种仅使用 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();
}
The if statements inside of each callback are what I use in my test to drive a success or error execution.
每个回调中的 if 语句是我在测试中用来驱动成功或错误执行的语句。
回答by damio
The solution given by @ggozad won't work if you use things like .complete()
.
如果您使用诸如.complete()
.
But, hooray, jasmine made a plugin to do exactly this: http://jasmine.github.io/2.0/ajax.html
但是,万岁,茉莉花做了一个插件来做到这一点: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');