我在测试函数的返回值时遇到问题,该函数在执行之前等待承诺被解析。
Javascript方法(serviceClient._getProduct返回一个jQuery ajax promise对象)
serviceClient.getProductName = function(id, storeId) {
$.when(self._getProduct(id)).done(function(data) {
return data.name;
});
};
测试代码
before(function() {
serviceClient.sampleResponse = fixture.load('product_response.json')[0];
$.ajaxStub = sinon.stub($, 'ajax').returns(new $.Deferred().resolve(serviceClient.sampleResponse));
});
describe('.getProductName', function() {
it('should return the product name', function() {
var name = serviceClient.getProductName(serviceClient.sampleResponse.id);
$.when($.ajaxStub.returnValue).done(function() {
expect(name).to.equal(serviceClient.sampleResponse.name);
});
});
});
当我逐步执行调用堆栈时,它似乎正在正确执行(在实际的js文件中的promise回调中的步骤,然后步入到断言的测试承诺回调),但是测试中的name变量仍然会到来回到未定义。任何反馈都将不胜感激。
答案 0 :(得分:0)
您正试图在data.name
中同步返回serviceClient.getProductName
,因为它依赖于异步的ajax请求而无法完成。
你在回调中做return data.name;
,这不会得到预期的结果:如果你同步回复某些内容,return
句应该在关闭之外的范围。
简化:如果有任何东西可以返回,那么它就是延期或承诺。它应该是这样的:
serviceClient.getProductName = function(id, storeId) {
var deferredName = $.Deferred();
$.when(self._getProduct(id)).done(function(data) {
deferredName.resolve(data.name);
}).fail(function(jqXHR, textStatus, error) {
deferredName.reject(error);
});
return deferredName.promise();
// Or, if needed (I don't think so, it's resolved and rejected here)
// return deferredName;
};
然后,在你的测试中:
before(function() {
serviceClient.sampleResponse = fixture.load('product_response.json')[0];
$.ajaxStub = sinon.stub($, 'ajax').returns(new $.Deferred().resolve(serviceClient.sampleResponse));
});
describe('.getProductName', function() {
it('should return the product name', function() {
serviceClient.getProductName(serviceClient.sampleResponse.id)
.done(function(name) {
expect(name).to.equal(serviceClient.sampleResponse.name);
});
});
});
抛开代码,概念上的错误是你可以从name
同步返回getProductName
,当该函数异常获取产品时(它无法访问其名称,直到延期已解决)。
注意:您可以使用getProductName
来实现then
,它返回一个Promise(它是Deferred的子集,但您通常可以使用它并且代码看起来很像甚至更清楚):
serviceClient.getProductName = function(id, storeId) {
return $.when(self._getProduct(id)).then(function(data) {
return data.name;
});
};
要删除它,也是不必要的$.when(...)
,您也可以从_getProduct
返回一个Promise(如果您已经延期,获得Promise就像调用{一样简单} {1}})。