当没有 $scope 强制摘要时,如何解决 AngularJS、Jasmine 2.0 中的承诺?
-
21-12-2019 - |
题
似乎承诺 不要在 Angular/Jasmine 测试中解析,除非你强制 $scope.$digest()
. 。在我看来,这是愚蠢的,但没关系,我在适用的情况下可以使用它(控制器)。
我现在所处的情况是我有一个服务,它不太关心应用程序中的任何范围,它所做的只是从服务器返回一些数据,但承诺似乎没有得到解决。
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();
});
解决方案
您需要在测试中注入生成的生成鸟类代码,并触发生成的$rootScope
。
其他提示
总是有$ rootscope,使用它
inject(function($rootScope){
myRootScope=$rootScope;
})
....
myRootScope.$digest();
. 所以整个下午我都在为此苦苦挣扎。读完这篇文章后,我也觉得答案有问题;事实证明是有的。上述答案都没有明确解释在何处以及为何使用 $rootScope.$digest
. 。所以,这就是我的想法。
首先为什么?你需要使用 $rootScope.$digest
每当您响应非角度事件或回调时。这将包括纯 DOM 事件、jQuery 事件和除 $q
这是角度的一部分。
其次在哪里?在您的代码中,而不是您的测试中。无需注射 $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
)的承诺,之后就是解决。您在承诺解决之前调用它,这导致it
终止条款。
从角度文档。
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);
}));
.