角度翻译单元测试 - 无法注入$ translateProvider

时间:2017-07-06 16:21:59

标签: javascript angularjs unit-testing es6-modules

我使用的是ES6,AngularJS,Karma / Jasmine和angular-translate。似乎无法让我的单元测试通过。在单元测试方面,不太确定如何使用第三方模块,如angular-translate。我得到的代码和错误如下。 $ translateProvider未加载。

import CatalogueModule from './catalogue.module'
import CatalogueService from './catalogue.service'

let service,
    _$translateProvider;

describe('CatalogueService', () => {
  beforeEach(angular.mock.module(CatalogueModule));

  beforeEach(() => {
    angular.mock.module({
      $translateProvider: jasmine.createSpyObj('$translateProvider',
        ['translations', 'preferredLanguage']
      ),
      $translate: jasmine.createSpyObj('$translate',
        ['use']
      )
    });
  })

  beforeEach(inject(($translateProvider) => {
    _$translateProvider = $translateProvider;

    _$translateProvider.translations('en', {});
    _$translateProvider.preferredLanguage('en');

    // service = new CatalogueService();
  }));

  it('should set the config object after initialization', inject(($translateProvider, CatalogueService) => {
    // $translateProvider.use.and.returnValue();
    // expect(service.config.headers).to.equal(null);
  }));
});

这是错误:

✖ "before each" hook: WorkFn for "should set the config object after initialization"
      Chrome 59.0.3071 (Mac OS X 10.12.3)
    Error: [$injector:unpr] Unknown provider: $translateProviderProvider <- $translateProvider

更新 - 添加catalogue.service.js

class CatalogueService {
  constructor($http, $q, $translate) {
    'ngInject';

    this._$http      = $http;
    this._$q         = $q;
    this._$translate = $translate;

    this.config = {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': '******',
        'P3-APP-ID': '*****',
        'P3-Date': '*****'
      }
    };

    this.catalogue = this.getCatalogue();
  }

  getCatalogue() {
    const lang = this._$translate.use();
    const url = `https://somedomain.com/catalog?language_code=${lang}`;
    const deferred = this._$q.defer();

    this._$http
      .get(url, this.config)
      .then(
        (res) => deferred.resolve(res.data.characters),
        (err) => deferred.reject(err)
      );

    return deferred.promise;
  };

  getCharacterByCharId(charId) {
    return this.catalogue
      .then((res) => {
        return res.find((character) => {
          return character.link_name === charId;
        });
      });
  };
}

export default CatalogueService;

2 个答案:

答案 0 :(得分:2)

没有

beforeEach(angular.mock.module(...))

在测试中。这意味着在当前测试中仅加载ngngMock模块,并且没有$translateProvider服务。

最好通过用DI实例化它们来测试角度单位,而不是直接测试。这允许测试服务注释和类内部。

非常希望保持单元测试被隔离并消除每个单元,但是测试中的单元,尤其是第三方库。如果测试单位需要$translateProvider,则最好将其替换为模拟或存根:

beforeEach(angular.mock.module('moduleThatContainsCatalogueService');

beforeEach(() => {
  angular.mock.module({
    $translateProvider: jasmine.createSpyObj('$translateProvider',
      ['translations', 'preferredLanguage', 'use']
    )
  });
})

it('...', inject(($translateProvider, catalogueService) => {
  $translateProvider.use.and.returnValue(...);
  ...
}));

答案 1 :(得分:0)

我之前使用$translateProvider的自定义加载程序完成了此操作。这个例子是打字稿,但是这样的东西对你也有用:

angular.mock.module(($provide: angular.auto.IProvideService, translateProvider: angular.translate.ITranslateProvider) => {
    $provide.factory('customLoader', ($q: angular.IQService) => 
        () => {
            const deferred = $q.defer();
            deferred.resolve({});
            return deferred.promise;
    });

    $translateProvider.useLoader('customLoader');
});