【发布时间】:2015-09-22 13:14:52
【问题描述】:
我们目前正在尝试测试我们的 Angular 服务,该服务使用 Promise 将值返回给控制器。问题是我们附加到 .then 的函数在 Jasmine 中没有被调用。
我们发现在返回 Promise 后向函数添加 $rootScope.digest() 可以调用同步 Promise,但它仍然不适用于异步 Promise。
到目前为止的代码是
beforeEach(inject(function (Service, $rootScope)
{
service = Service;
root = $rootScope;
}));
it('gets all the available products', function (done)
{
service.getData().then(function (data)
{
expect(data).not.toBeNull();
expect(data.length).toBeGreaterThan(0);
done();
});
root.$digest();
});
在这种情况下,promise 可以正常调用,但如果它是异步的,则不会调用它,因为在调用 root.$digest() 时,promise 还没有准备好进行“消化”。
有没有什么方法可以告诉我什么时候承诺在解决之后才能调用摘要?或者可能会自动执行此操作?谢谢;)
我们必须测试的部分服务(删除错误处理):
var app = angular.module('service', []);
/**
* Service for accessing data relating to the updates/downloads
* */
app.factory('Service', function ($q)
{
... init
function getData()
{
var deffered = $q.defer();
var processors = [displayNameProc];
downloads.getData(function (err, data)
{
chain.process(processors, data, function (err, processedData)
{
deffered.resolve(processedData);
});
});
return deffered.promise;
}
...
在出现问题的情况下,当 service.getData 为异步时,promise 已解决,但由于 root.$digest 已被调用,因此未调用测试代码中附加到该 promise 的函数。希望这能提供更多信息
解决方法
var interval;
beforeEach(inject(function ($rootScope)
{
if(!interval)
{
interval = function ()
{
$rootScope.$digest();
};
window.setInterval(interval, /*timing*/);
}
}));
我最终使用上面的解决方法重复调用摘要,这样每一层承诺都有机会运行......它并不理想或漂亮,但它适用于测试......
【问题讨论】:
-
您是否在嘲笑您的服务以及返回的承诺?
-
不,我正在尝试测试实际服务。
-
如果您正在测试实际服务并且它在内部使用 $http 服务,那么我相信当远程调用成功或失败时,angularjs 会启动摘要。
-
是的,我认为可能是这种情况,但不幸的是,我们的大多数服务都没有使用 http 请求。目前我可以添加一个技巧来重复调用摘要,这有点解决这个问题,但这不是一个很好的解决方案。如果有某种机制可以判断承诺何时解决但未消化,那就太好了。
-
您是否有机会发布更多代码或创建小提琴/plunk?
标签: javascript angularjs jasmine angular-promise