2017-07-06 18 views
1

私はES6、AngularJS、カルマ/ジャスミン、角度変換を使用しています。私の単体テストに合格することができないようです。単体テストになると、角翻訳のようなサードパーティ製のモジュールでどうやって作業するかはあまりにも分かりません。コードと私が得ているエラーは以下の通りです。 $ 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 

UPDATE - 追加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でインスタンス化することでテストすることが望ましいです。これにより、サービス注釈とクラス内部の両方をテストすることができます。

単体テストを分離したままにして、すべての単体テストを排除してテストしたもの、特に第三者のライブラリをテストすることが非常に望ましいです。テストユニットは$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:未定義のプロパティ '使用'を読み取ることができません – zee

+0

基本的に、$ translateはCatalogueServiceのDIとして設定または渡されていません。 – zee

+0

すべての依存関係を 'new'で手動で渡すか、またはDIを使用してそれをインスタンス化するかを選択できます。 2つ目のオプションは、完全なカバレッジのために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'); 
}); 
関連する問題