Jasmine中返回Deferred的模拟嵌套函数
Mocking nested function returning Deferred in Jasmine
我正试图为一个使用名为jQuery.rest 的jQuery ajax包装库的模块编写Jasmine测试
该测试模块:
var module = function() {
function getData(callback) {
IP.read().done(function (data) {
console.log("done");
callback(data);
});
}
return {
getData: getData
}
}();
client
和IP
变量在不同的文件中声明,如下所示:
var client = new $.RestClient('/rest/api/');
var IP = client.add('ip');
我想模拟read()
函数,这样它就会返回我在测试中定义的Json有效负载。read()
方法返回一个$.Deferred
对象。
我尝试过不同的方法(使用Jasmine间谍),但没有成功。
我看到了两种方法:
-
监视
$.ajax()
并调用返回您自己的延迟的fake函数Contra:您间接测试库
-
模拟
$.RestClient
的接口并返回您自己的延迟Contra:当不仅需要测试回调时,还要做更多的工作来模拟库。(你的嘲讽越复杂,你的测试就越容易出错。)
TL;DR如果已知,则跳过此项。
但首先让我们看看RestClient是如何工作的。。。它有两个基本对象,一个资源和一个动词。RestClient实际上是一个Resource
对象(1)。当CCD_ 11返回一个休息片段(2)时,CCD_ 9对象将返回另一个CCD_。预定义的谓词read
将返回Verb
实例的call
方法(3)。
- https://github.com/jpillora/jquery.rest/blob/gh-pages/dist/jquery.rest.js#L382
- https://github.com/jpillora/jquery.rest/blob/gh-pages/dist/jquery.rest.js#L241
- https://github.com/jpillora/jquery.rest/blob/gh-pages/dist/jquery.rest.js#L245
从该链的底部到顶部,可以从call()
方法(4)访问request
方法。如果未明确重写,则默认为$.ajax()
。(5)
- https://github.com/jpillora/jquery.rest/blob/gh-pages/dist/jquery.rest.js#L174
- https://github.com/jpillora/jquery.rest/blob/gh-pages/dist/jquery.rest.js#L66
如果没有不同的配置,对read()
的调用将导致对$.ajax()
的调用,并返回promise。
所以,当做新的new $.RestClient().add("...").add("...").read()
时,你会得到$.ajax()
的效果。
变体1:
describe("getData()", function(){
// Handle to ajax()' deferred, scoped to the
// describe so the fake ajax() and the it()
// have access to it
var def,
underTest;
beforeEach(function(){
// Mock $.ajax (or what a Verb calls in the end)
// assign "def" with a deferred and return it,
// the test can then resolve() or reject() it
spyOn($, "ajax").and.callFake(function(opts) {
def = $.Deferred();
return def;
});
// This is under test
underTest = new UnderTest();
});
afterEach(function(){
// Ensure a missing call of ajax() will fail the test
def = null;
});
it("should call callback on successful read", function() {
var callback = jasmine.createSpy("callback");
// Indirectly call ajax() which will create def
underTest.getData(callback);
// Resolve the deferred to succeed the response
def.resolve({a: 1});
expect(callback).toHaveBeenCalledWith({a: 1});
});
it("should not call callback on failed read", function(){
var callback = jasmine.createSpy("callback");
underTest.getData(callback);
def.reject();
expect(callback).not.toHaveBeenCalled();
});
});
假的是返回一个延迟的,而不是承诺,但在这种情况下,这是可以的,因为它有相同的接口,除了我们之外,任何人都不应该拒绝或解决延迟。
变体2:
describe("getData()", function(){
// Store original reference
var origRestClient,
// See first code block
def,
underTest;
// Mock thr Resouce object
function MockResource() { }
// Simplify the behaviour of this mock,
// return another Mock resource
MockResource.prototype.add = function() {
return new MockResource();
};
// What Verb.call() would do, but directly
// return a deferred
MockResource.prototype.read = function() {
def = $.Deferred();
return def;
};
beforeEach(function(){
// Replace RestClient
origRestClient = $.RestClient;
$.RestClient = MockResource;
underTest = new UnderTest();
});
afterEach(function(){
// Restore RestClient
$.RestClient = origRestClient;
def = null;
});
it("should call callback on successful read", function() {
var callback = jasmine.createSpy("callback");
underTest.getData(callback);
def.resolve({a: 1});
expect(callback).toHaveBeenCalledWith({a: 1});
});
it("should not call callback on failed read", function(){
var callback = jasmine.createSpy("callback");
underTest.getData(callback);
def.reject();
expect(callback).not.toHaveBeenCalled();
});
});
如果您也想测试路径和请求数据,那么对Resouce
的嘲讽需要比我所做的更多的工作,而使用上面的代码,这是不可能的。
- 用嵌套函数和默认函数定义函数
- 如何在ReactJS JSX中执行嵌套的if-else语句
- 可以简化嵌套的延迟Q Promises解析吗
- 用于搜索的聚合物嵌套绑定
- 如何使用javascript获取嵌套对象中所有子对象的单个属性
- d3中堆栈函数和嵌套函数之间的差异
- 如何打印嵌套对象的所有值
- JavaScript 中的嵌套函数和 “this” 关键字
- 设置嵌套对象属性的更好方法
- querySelector/getElementByClassName嵌套项的顺序
- 猫鼬在特定记录中查找嵌套记录
- 访问嵌套JSON对象的键,其中键是动态的
- D3嵌套组作为x轴
- Jasmine中返回Deferred的模拟嵌套函数
- 如何在 Javascript 中创建一个模拟 100 行和 10 列网格的嵌套循环
- 如何为具有嵌套函数(javascript,jasmine)的第三方库编写模拟
- 使用模拟工厂在茉莉花中测试嵌套承诺
- 使用嵌套类来模拟 ES6 中的命名空间
- 模拟 Node.js 中的嵌套模块
- 使用setInterval模拟setTimeout不适用于嵌套