javascript 在 angularjs 中对异步服务进行单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15477370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit testing an asynchronous service in angularjs
提问by Hidden Developer
I am trying to unit test a service which has asynchronous methods but am having no luck.
我正在尝试对具有异步方法但没有运气的服务进行单元测试。
I have tried to implement with promises by using the $q support in angularjs.
我试图通过使用 angularjs 中的 $q 支持来实现承诺。
Any help would be appreciated.
任何帮助,将不胜感激。
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);
});
}));
});
回答by pkozlowski.opensource
First of all, the setTimeout
is particularly tricky to test since it hard to mock. Fortunately AngularJS has a wrapper around it ($timeout
) that plays the same role but can be easily mocked:
首先,setTimeout
由于难以模拟,所以测试特别棘手。幸运的是 AngularJS 有一个包装器 ( $timeout
) ,它扮演着同样的角色,但很容易被嘲笑:
ls.DoIt = function() {
var deferred = $q.defer();
$timeout(function(){
deferred.resolve(5);
},3000);
return deferred.promise;
}
The mock provided for $timeout
allows us to easily simulate elapsed time (with $timeout.flush()
) which means our tests can run fast, without really waiting for the async event to complete (please note that the production code is still using async API!).
提供的模拟$timeout
允许我们轻松模拟经过的时间(使用$timeout.flush()
),这意味着我们的测试可以快速运行,而无需真正等待异步事件完成(请注意,生产代码仍在使用异步 API!)。
The changed tests would look like:
更改后的测试如下所示:
it("should equal 5", inject(function(myservice, $timeout) {
var valueToVerify;
myservice.DoIt().then(function(returned) {
valueToVerify = returned;
});
$timeout.flush();
expect(valueToVerify).toEqual(5);
}));
And finally the working jsFiddle: http://jsfiddle.net/v9L9G/1/
最后是工作 jsFiddle:http: //jsfiddle.net/v9L9G/1/
回答by Caio Cunha
It's not related to Angular itself, but to Jasmine async tests.
它与 Angular 本身无关,而是与Jasmine 异步测试相关。
If you need a setTimeout
use Angular $timeout
. And if you wish to have a fine control over setTimeout/$timeout executions, use mocked Clock.
如果您需要setTimeout
使用 Angular $timeout
。如果您希望对 setTimeout/$timeout 执行进行精细控制,请使用模拟 Clock。