2017-07-06 121 views
1

我正在使用ES6,AngularJS,Karma/Jasmine和角度翻譯。似乎無法讓我的單元測試通過。在單元測試方面,不太確定如何使用第三方模塊,如角度平移。代碼和我得到的錯誤如下。 $ 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; 

回答

1

沒有

beforeEach(angular.mock.module(...)) 
測試

。這意味着在當前測試中僅加載了ngngMock模塊,並且沒有$translateProvider服務。

最好使用DI來實例化它們,而不是直接測試Angular單元。這允許測試服務註釋和類內部。

非常希望保持單元測試的隔離性並消除每個單元,但是要從測試中測試一個單元,特別是第三方庫。如果測試單位要求$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(...); 
    ... 
})); 
+0

感謝您的支持。得到它與您的建議一起工作。我也更新了我的問題,以包含使用$ translate的CatalogueService服務。問題是現在我收到以下錯誤: TypeError:無法讀取未定義的屬性'use' – zee

+0

基本上,$ translate沒有被設置或作爲CatalogueService中的DI傳入。 – zee

+0

您可以選擇使用'new'手動傳遞所有依賴關係,或者使用DI來實例化它。第二種選擇是更優選的,因爲您需要以完全覆蓋的任何方式測試DI註釋。 – estus

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'); 
});