【问题标题】:Angularjs how can I unit test a Service which depends on another Service with promises?Angularjs如何对依赖于另一个带有承诺的服务的服务进行单元测试?
【发布时间】:2023-03-29 17:49:01
【问题描述】:

如何测试依赖于其他服务的服务。我目前在此实现中未找到 Service1Provider 错误。如何正确注入 Service1,以便对 Service2 进行单元测试?感谢您提供任何提示或技巧。

jsfiddle gist

!function(ng){
'use strict';

 var module = ng.module('foo.services', []);

(function($ng, $module) {
  function Service($q) {

    return {
        bar: function(a,b,c){

            var baz = a+b+c;
            return function(d,e,f){

                var deferred = $q.defer();
                if(baz > 0){
                  deferred.resolve({result: baz + d + e + f });
                } else {
                  deferred.reject({ err: 'baz was <= 0'})
                }
                return deferred.promise;

            }
        }
    };
  }

   $module.factory("Service1", ['$q', Service]);

 })(ng, module);

  (function($ng, $module) {
    function Service(Service1) {

       function doSomething(){

        var result;
        var whatever = Service1.bar(5,6,7);

         var promise = whatever(8,9,10);
        promise.then(function(data){

            result = data.result;
            //data.result should be 45 here
        }, function(err){

        });

        return result;
    }

    return {
        bam:doSomething
    };
}

  $module.factory("Service2", ["Service1", Service]);

  })(ng, module);
}(angular);


var myApp = angular.module('myApp',['foo.services']);

【问题讨论】:

  • Hcabnettek,我只能建议需要修改 Service2 以接受服务作为传递给 doSomething 的参数,否则 Service2 对 Service1 的依赖对 Service2 来说是不可穿透的。如果您正在寻找可能出现问题的答案,则无法从 doSomething 直接返回 result - 您需要返回 promise
  • 其实修改需要稍微大一些。返回的promise需要考虑到链式.then(),其回调应该返回data.result`(我认为)。

标签: unit-testing angularjs jasmine deferred


【解决方案1】:

如果您只是在测试 Service2,那么您应该尝试在测试中消除对 Service1 的任何依赖。您的测试可能有以下内容:

module('foo.services', function($provide) {
  $provide.value('Service1', MockService1());
});

这将给出函数 MockService1 的返回值,而不是在注入服务时实际使用该服务。

然后你让 MockService1 函数返回具有相同功能的实际服务的骨架。在您的测试中,您可以等待通过执行以下操作来解决承诺:

bar: function(...) {
  var def = $q.defer();
  $timeout(function() {
    def.resolve('test');
  });
  return def.promise;
}

// This is in your test
bar.then( /* .... some tests */ );
// This executes the timeout and therefor the resolve
$rootScope.$digest();
$timeout.flush();

希望这有帮助

【讨论】:

  • 这不是一个坏主意,但是,如果被模拟的服务很大或未知(例如,有很多意外错误),它几乎不会有帮助。就我而言,我正在使用 express-cassandra 进行测试,并且做一个有效的模型需要几个月的工作......
猜你喜欢
  • 2019-04-12
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多