我正在尝试对具有异步方法但没有运气的服务进行单元测试。
我试图通过在angularjs中使用$ q支持来实现promises。
任何帮助都将不胜感激。
angular.module('myapp', ['myservice']);
angular.module('myservice', []).factory('myservice', function($q) {
var ls = {};
ls.DoIt = function() {
var deferred = $q.defer();
setTimeout(function(){
deferred.resolve(5);
},3000);
return deferred.promise;
}
return ls;
});
describe('services', function () {
beforeEach(module('myservice'));
it("should equal 2", inject(function(myservice) {
myservice.DoIt().then(function(returned) {
expect(returned).toEqual(2);
});
}));
});
答案 0 :(得分:30)
首先,setTimeout
特别难以测试,因为它难以模拟。幸运的是,AngularJS有一个包装器($timeout
),它起着相同的作用,但很容易被嘲笑:
ls.DoIt = function() {
var deferred = $q.defer();
$timeout(function(){
deferred.resolve(5);
},3000);
return deferred.promise;
}
为$timeout
提供的模拟允许我们轻松模拟已用时间(使用$timeout.flush()
),这意味着我们的测试可以快速运行,而无需等待异步事件完成(请注意生产代码仍在使用异步API!)。
更改后的测试如下:
it("should equal 5", inject(function(myservice, $timeout) {
var valueToVerify;
myservice.DoIt().then(function(returned) {
valueToVerify = returned;
});
$timeout.flush();
expect(valueToVerify).toEqual(5);
}));
最后工作的jsFiddle:http://jsfiddle.net/v9L9G/1/
答案 1 :(得分:4)
它与Angular本身无关,而与Jasmine async tests无关。
如果您需要setTimeout
使用Angular $timeout
。如果您希望对setTimeout / $ timeout执行进行精细控制,请使用mocked Clock。