似乎承诺do not resolve in Angular/Jasmine tests unless you force a $scope.$digest()
。这是愚蠢的IMO,但很好,我在适用的地方工作(控制器)。
我现在的情况是我有一个服务,它可以不关心应用程序中的任何作用域,它只是从服务器返回一些数据,但承诺似乎并没有解决
app.service('myService', function($q) {
return {
getSomething: function() {
var deferred = $q.defer();
deferred.resolve('test');
return deferred.promise;
}
}
});
describe('Method: getSomething', function() {
// In this case the expect()s are never executed
it('should get something', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
expect(1).toEqual(2);
});
done();
});
// This throws an error because done() is never called.
// Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
it('should get something', function(done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
expect(1).toEqual(2);
done();
});
});
});
测试此功能的正确方法是什么?
编辑:供参考的解决方案。显然,即使服务没有使用它,你也不得不注入和消化$ rootScope。
it('should get something', function($rootScope, done) {
var promise = myService.getSomething();
promise.then(function(resp) {
expect(resp).toBe('test');
});
$rootScope.$digest();
done();
});
答案 0 :(得分:41)
您需要在测试中注入$rootScope
并在其上触发$digest
。
答案 1 :(得分:12)
总是有$ rootScope,使用它
inject(function($rootScope){
myRootScope=$rootScope;
})
....
myRootScope.$digest();
答案 2 :(得分:3)
所以我整个下午都在努力。看完这篇文章之后,我也觉得答案中有些东西;事实证明有。上述答案均未明确说明使用$rootScope.$digest
的位置和原因。所以,这就是我想出来的。
首先为什么?每当您从非角度事件或回调响应时,您都需要使用$rootScope.$digest
。这将包括纯DOM事件,jQuery事件以及$q
以外的其他第三方Promise库,它们是角度的一部分。
其次在哪里?在你的代码中,不是你的测试。无需在您的测试中注入$rootScope
,只需在您的实际角度服务中使用它。这就是所有上述内容都无法弄清楚答案是什么,他们将$rootScope.$digest
显示为从测试中调用。
我希望这有助于下一个长期存在同样问题的人。
昨天我被删除了这篇文章。今天我继续遇到这个问题,尝试使用上面提到的慷慨解答。所以,我以声誉点为代价来等待我的答案,因此,我取消了它。
这是您在非角度事件处理程序中所需要的,并且您正在使用$ q并尝试使用Jasmine进行测试。
something.on('ready', function(err) {
$rootScope.$apply(function(){deferred.resolve()});
});
请注意,在某些情况下可能需要将其包装在$ timeout中。
something.on('ready', function(err) {
$timeout(function(){
$rootScope.$apply(function(){deferred.resolve()});
});
});
还有一点需要注意。在原始问题示例中,您在错误的时间调用
done
。在结算后,您需要在承诺的done
方法(或then
或catch
)内调用finally
。您在promise解析之前调用它,这导致it
子句终止。
答案 3 :(得分:3)
来自角度文档。
https://docs.angularjs.org/api/ng/service/ $ Q
it('should simulate promise', inject(function($q, $rootScope) {
var deferred = $q.defer();
var promise = deferred.promise;
var resolvedValue;
promise.then(function(value) { resolvedValue = value; });
expect(resolvedValue).toBeUndefined();
// Simulate resolving of promise
deferred.resolve(123);
// Note that the 'then' function does not get called synchronously.
// This is because we want the promise API to always be async, whether or not
// it got called synchronously or asynchronously.
expect(resolvedValue).toBeUndefined();
// Propagate promise resolution to 'then' functions using $apply().
$rootScope.$apply();
expect(resolvedValue).toEqual(123);
}));