我希望重用我的模拟,而不必在每个将它们作为依赖项的单元测试中进行设置。但是我很难弄清楚如何正确注射它们。

这是我进行单元测试设置的尝试,由于ConfigServiceMockProvider不存在,因此当然失败了。

describe('LoginService tests', function () {

  var LoginService;

  beforeEach(module('mocks'));

  beforeEach(module('services.loginService', function ($provide, _ConfigServiceMock_) {
    $provide.value("ConfigService", _ConfigServiceMock_);

    /* instead of having to type e.g. everywhere ConfigService is used
    *  $provide.value("ConfigService", { 'foobar': function(){} });
    */
  });

  beforeEach(inject(function (_LoginService_) {
    LoginService = _LoginService_;
  });
}


ConfigServiceMock

angular.module('mocks').service('ConfigServiceMock', function() {
  this.init = function(){};
  this.getValue = function(){};
}


我意识到我可能可以让ConfigServiceMock.js创建一个全局窗口对象,从而不需要像这样加载它。但是我觉得应该有更好的方法。

最佳答案

尝试这样的事情:

describe('Using externally defined mock', function() {
  var ConfigServiceMock;

  beforeEach(module('mocks'));

  beforeEach(module('services.configService', function($provide) {
    $provide.factory('ConfigService', function() {return ConfigServiceMock;});
  }));

  beforeEach(module('services.loginService'));

  beforeEach(inject(function (_ConfigServiceMock_) {
    ConfigServiceMock = _ConfigServiceMock_;
  }));

  // Do not combine this call with the one above
  beforeEach(inject(function (_LoginService_) {
    LoginService = _LoginService_;
  }));

  it('should have been given the mock', function() {
    expect(ConfigServiceMock).toBeDefined('The mock should have been defined');
    expect(LoginService.injectedService).toBeDefined('Something should have been injected');
    expect(LoginService.injectedService).toBe(ConfigServiceMock, 'The thing injected should be the mock');
  });
});


根据this answer,您必须将所有呼叫module放在所有呼叫inject之前。

这引入了一个catch 22的问题,因为您必须在规范中具有对ConfigServiceMock的引用(通过inject),然后才能在LoginService上进行设置(在module调用中完成)

解决方法是将角度工厂函数设置为ConfigService依赖项。这将导致angular延迟加载服务,届时您将收到对ConfigServiceMock的引用。

09-25 19:46