我有一个函数可以对服务进行 AJAX 调用。我试图期望在失败时调用 displayError 函数。
我有一个接受 url 的函数 ajaxCall。成功后,我将结果传递给 displaySuccess,出现错误时,我将详细信息传递给 displayError。
function ajaxCall(url) {
$.ajax({
method: "GET",
url: url,
data: "json",
beforeSend: function (xhr) {
//Do Stuff
},
error: function(xhr, textStatus, errorThrown) { displayError(xhr, textStatus, errorThrow, url)},
success: function (results) { displaySuccess(result) }
});
}
function displayError(xhr, textStatus, errorThrow, url) {
//Do Stuff//
}
function displaySuccess(results) {
//Do Stuff//
}
在 Jasmine 中,我成功地验证了 URL。我的问题是测试以确保调用 displayError 和 displaySuccess 函数。
到目前为止,我对这个具体问题有以下看法。
describe('The ajaxCall component', function() {
it('should call the error function when the ajax call fails', function () {
var obj = {};
spyOn(obj, 'displayError');
spyOn($, "ajax").and.callFake(function (options) {
options.error();
});
ajaxCall('/myResource/get');
expect(obj.method).toHaveBeenCalled();
});
}
我对单元测试有点陌生,我进行了搜索,试图找到有帮助的建议,但它们会使单元测试失败。我哪里出错了?
最佳答案
这一切都归结为您如何监视您的对象并编写更可测试的代码。让我们研究一些策略。
策略一
鉴于您当前的代码不在一个对象中,您可以通过简单地直接测试它们的实现来测试这些函数是否被调用。
您无需测试函数是否被调用,而是直接测试它们的实现。
示例
describe("strategy 1", function () {
var ajaxSpy;
beforeEach(function () {
ajaxSpy = spyOn($, 'ajax');
ajaxCall();
});
describe("error callback", function () {
beforeEach(function() {
spyOn(window, 'alert');
var settings = ajaxSpy.calls.mostRecent().args[0];
settings.error();
});
describe("when there is an error", function() {
it("should alert an error message", function() {
expect(window.alert).toHaveBeenCalledWith('Error');
});
});
});
});
策略2
虽然上述方法有效,但编写测试可能会很麻烦。理想情况下,您希望分别测试调用和实现。
为此,我们可以监视这些函数。由于它们位于全局命名空间中,您可以通过 window
对象监视它们。
示例
describe("strategy 2", function () {
var ajaxSpy;
beforeEach(function () {
ajaxSpy = spyOn($, 'ajax');
ajaxCall();
});
describe("error callback", function () {
beforeEach(function() {
spyOn(window, 'displayError');
var settings = ajaxSpy.calls.mostRecent().args[0];
settings.error();
});
describe("when there is an error", function() {
it("should alert an error message", function() {
expect(window.displayError).toHaveBeenCalled();
});
});
});
});
策略三(推荐)
最终的策略,也是我推荐的,与第二种策略有相似的设置,除了我们将我们的实现封装到一个自定义对象中。
这样做可以通过将功能包装在对象中并避免全局命名空间(即 window
)使代码更易于测试。
示例
describe("solution 3", function() {
var ajaxSpy;
beforeEach(function() {
ajaxSpy = spyOn($, 'ajax');
ajaxService.ajaxCall();
});
describe("error callback", function() {
beforeEach(function() {
spyOn(ajaxService, 'displayError');
var settings = ajaxSpy.calls.mostRecent().args[0];
settings.error();
});
it("should alert an error message", function() {
expect(ajaxService.displayError).toHaveBeenCalled();
});
});
});
关于javascript - 使用 Jasmine 测试从 jQuery AJAX 回调调用的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37731995/