如何为测试目的重新创建 AngularJS 服务?

How to recreate AngularJS service for testing purposes?

我想测试 myService 初始化,这可能会因条件而异:

service('myService', function(internalService){
   if(internalService.param){ init1(); }
   else { init2(); }

   //...
});

我可以模拟 internalService,但如何重新创建 myService

服务在配置阶段后由注入器 (inject(...)) 实例化。要测试您的初始化,您需要做的就是在每个测试中进行不同的设置。也就是说,与其在 beforeEach 块中实例化您的服务,不如在测试中进行。

例如,您可以通过模拟 internalService 具有 param: true

来测试使用 init1 实例化的副作用
describe('Unit: myService', function() {
  it('should perform init1 if internalService.param', function() {
    var mockInternalService = {
      param: true,
    };

    // config phase (mocking)
    module('app', function($provide) {
      $provide.constant('internalService', mockInternalService);
    });

    inject(function($injector) {
      myService = $injector.get('myService');

      // assert side effects from init1();
    });
  });
});

为了测试 init2 的副作用,只需将 internalService 模拟为 param: false

  it('should perform init2 if !internalService.param', function() {
    var mockInternalService = {
      param: false,
    };

    // config phase (mocking)
    module('app', function($provide) {
      $provide.constant('internalService', mockInternalService);
    });

    inject(function($injector) {
      myService = $injector.get('myService');

      // assert side effects from init2();
    });
  });

编辑:当然,如果您想对每个配置进行 多次 测试,您可以创建两个 describe 块,其中 beforeEach 不同。

  describe('Unit: myService', function() {
    var myService;

    describe('When instantiated with `init1`', function() {
      beforeEach(config(true));
      beforeEach(inject(injections));

      it('should do X');
    });

    describe('When instantiated with `init2`', function() {
      beforeEach(config(false));
      beforeEach(inject(injections));

      it('should do Y');
    });

    function config(param) {
       return function() { 
         var mockInternalService = {
           param: param,
         };

         // config phase (mocking)
         module('app', function($provide) {
           $provide.constant('internalService', mockInternalService);
         });
      };
    }

    function injections($injector) {
      myService = $injector.get('myService');
    }
  });