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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 00:55:12  来源:igfitidea点击:

Unit testing an asynchronous service in angularjs

javascriptunit-testingasynchronousangularjs

提问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.

任何帮助,将不胜感激。

http://jsfiddle.net/9pBze/37/

http://jsfiddle.net/9pBze/37/

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 setTimeoutis 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 $timeoutallows 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 setTimeoutuse Angular $timeout. And if you wish to have a fine control over setTimeout/$timeout executions, use mocked Clock.

如果您需要setTimeout使用 Angular $timeout。如果您希望对 setTimeout/$timeout 执行进行精细控制,请使用模拟 Clock