40

私はここ ( http://pascalprecht.github.io/angular-translate/ ) から angular translate を使用しており、正常に動作しますが、コントローラーの単体テストでエラーが発生します:

Unexpected request: GET scripts/i18n/locale-en.json

私はなぜ理解していないのですか?

私は yeoman を使用し、カルマでテストします。

app.js:

'use strict';

(function() {

  angular.module('wbApp', ['authService', 'authUserService', 'checkUserDirective', 'ui.bootstrap', 'pascalprecht.translate'])
    .config(function($routeProvider) {
      $routeProvider
        .when('/', {
          templateUrl: 'views/login.html',
          controller: 'LoginCtrl',
          access: {
            isFree: true
          }
        })
        .when('/main', {
          templateUrl: 'views/main.html',
          controller: 'MainCtrl',
          access: {
            isFree: false
          }
        })
        .otherwise({
          redirectTo: '/'
        });
    });

})();

configTranslate.js:

'use strict';

(function() {

  angular.module('wbApp')
    .config(['$translateProvider',
      function($translateProvider) {

        $translateProvider.useStaticFilesLoader({
            prefix: 'scripts/i18n/locale-',
            suffix: '.json'
        });

        $translateProvider.preferredLanguage('en');

      }]);

})();

カルマ.conf.js:

files = [

  ...

  'app/bower_components/angular-translate/angular-translate.js',
  'app/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',

  ...

];

コントローラーテスト:

'use strict';

describe('Controller: LoginCtrl', function() {

  // load the controller's module
  beforeEach(module('wbApp'));

  var LoginCtrl, scope, location, httpMock, authUser;

  // Initialize the controller and a mock scope
  beforeEach(inject(function($controller, $rootScope, $location, $httpBackend, AuthUser) {
    authUser = AuthUser;
    location = $location;
    httpMock = $httpBackend;
    scope = $rootScope.$new();

    LoginCtrl = $controller('LoginCtrl', {
      $scope: scope
    });


    httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();

  }));

  it(...);

  ...

});

これをテスト コントローラーに追加すると、同じエラーが生成されます。

httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(200);
httpMock.flush();

また

httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.flush();

私はこの投稿を見つけましたApp Configで初期化されたAngular Translateでコントローラーをテストするにはどうすればよいですか? しかし、私を助けませんでした:/

私はテストで $httpBackend を広く使用しており、正常に動作しますが、この場合は効果がありません。行にコメントすると:

$translateProvider.preferredLanguage('en');

(コントローラーで)ランタイムを追加すると、明らかにエラーになります

$translate.uses(local);

私は同じエラーで終わりますか?

したがって、翻訳構成 (configTranslate.js) に目を向けても、実行時に同じ結果が得られます。

Unexpected request: GET scripts/i18n/locale-en.json

これは、「beforeEach(inject(function(...});」のいずれか)でテストした構文です。

またはテストで "it('...', function() {...});"

httpMock.expectGET('scripts/i18n/locale-en.json');
httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(data);

最後に

httpMock.flush();

$ apply も試しました

httpMock.expectGET('scripts/i18n/locale-fr.json');
scope.$apply(function(){
  $translate.uses('fr');
});
httpMock.flush();

何も起こらない、それでもこのエラーは私を夢中にさせている..

何か提案があれば

4

11 に答える 11

28

これは既知の問題です。こちらのドキュメントに従ってください: unit testing angular

ソリューション

残念ながら、この問題は angular-translate の設計が原因です。これらのエラーを回避するには、非同期ローダーをまったく使用しないように、テスト スイートのモジュール構成を上書きするだけです。非同期ローダーがない場合、XHR がないため、エラーは発生しません。

では、実行時にテスト スイートのモジュール構成を上書きするにはどうすればよいでしょうか。angularモジュールをインスタンス化するとき、構成関数として実行されるインライン関数をいつでも適用できます。すべてのプロバイダーにアクセスできるため、この構成関数を使用してモジュール構成を上書きできます。

$provide プロバイダーを使用して、静的ファイル ローダーの代わりに使用するカスタム ローダー ファクトリを構築できます。

beforeEach(module('myApp', function ($provide, $translateProvider) {

  $provide.factory('customLoader', function () {
    // loader logic goes here
  });

  $translateProvider.useLoader('customLoader');

}));

上記のリンクで詳細をお読みください。

于 2014-11-28T17:39:12.103 に答える
12

解決策が欲しかったのですが、

  1. あまりにもハッキーではありませんでした
  2. 実際のアプリケーション コードを変更する必要はありませんでした。
  3. 追加のモジュールをロードする機能を妨げない
  4. そして最も重要なことは、すべてのテストを変更する必要がないことです。

これは私が最終的に得たものです:

// you need to load the 3rd party module first
beforeEach(module('pascalprecht.translate'));
// overwrite useStaticFilesLoader to get rid of request to translation file
beforeEach(module(function ($translateProvider) {
    $translateProvider.useStaticFilesLoader = function () {
    };
}));

単体テストに実際の翻訳が必要ないと仮定すると、これはうまく機能します。beforeEach をグローバル レベル、できればテスト フォルダー内の独自のファイルに配置するだけです。その後、他のすべてのテストの前に実行されます。

于 2015-12-15T19:47:54.390 に答える
4

分度器テストでこの問題が発生しました。私の解決策は、次のような翻訳を模擬することでした:

angular.module('app')
        .config(function ($translateProvider) {
            $translateProvider.translations('en', {});
            $translateProvider.preferredLanguage('en');
        })

これで、言語ファイルはダウンロードされず、文字列は翻訳されず、仕様の文字列キーに対してテストするだけです:

expect(element(by.css('#title')).getText()).toEqual('TITLE_TEXT');
于 2015-09-25T08:53:43.970 に答える
3

メソッドをテストしてみてください:

it('should ...', function() {
    httpMock.when('GET', 'scripts/i18n/locale-en.json').respond({});
    httpMock.expectGET('scripts/i18n/locale-en.json');
    scope.resetForm(); // Action which fires a http request
    httpMock.flush(); // Flush must be called after the http request
}

Angular ドキュメントの例を参照してください

于 2013-09-19T09:37:21.207 に答える
1

解決策はどれもうまくいきませんでしたが、次の解決策がありました。

1) を使用する必要がある場合scope.$apply()、またはテストで状態を処理する必要がある場合 ( 2 番目のアプローチが機能しない場合)、プラグインを使用$apply()してメソッドでアプリの翻訳をオーバーライドし、JSON ファイルを読み込みます。$translateProvider.translations()

beforeEach(module(function ($translateProvider) {
    $translateProvider.translations('en', readJSON('scripts/i18n/locale-en.json'));
}));

2) テストしたコントローラーがサービスに依存している$translate場合は、プラグインを使用してJSON ファイルをロードし、それを組み合わせて$httpBackend、angular-translate が要求したときにロケール ファイルをロードできます。

beforeEach(inject(function (_$httpBackend_) {
    $httpBackend = _$httpBackend_;

    $httpBackend.whenGET('scripts/i18n/locale-en.json').respond(readJSON('scripts/i18n/locale-en.json'));
    $httpBackend.flush();
})));

これを下回る必要があることに注意してください。そうしbeforeEach(module('myApp'));ないと、$injectorエラーが発生します。

于 2015-09-05T04:27:30.780 に答える
0

私はこのパターンを使用します。

  • ApplicationModule は通常の angular-translate 構成を設定します。
  • テスト コードは、'applicationModule' の代わりに 'testModule' をロードします

// application module .js 
(function() {
  'use strict'; 
  
  angular
   .module('applicationModule', [
    'ngAnimate',
    'ngResource',
    'ui.router',
    'pascalprecht.translate'
  ])
  .config(['$stateProvider', '$urlRouterProvider', '$translateProvider', '$translatePartialLoaderProvider', config]);

  function config($stateProvider, $urlRouterProvider, $translateProvider, $translatePartialLoaderProvider) {
    // set routing ... 
        
    $translateProvider.useStaticFilesLoader({
      prefix: 'i18n/locale-',
      suffix: '.json'
    });

    $translateProvider.useMessageFormatInterpolation();
    $translateProvider.fallbackLanguage(['en']);
    $translateProvider
    .registerAvailableLanguageKeys(['en', 'ko'], {
      'en_US': 'en',
      'ko_KR': 'ko'
    })
    .determinePreferredLanguage(navigator.browserLanguage);

            
    $translateProvider.addInterpolation('$translateMessageFormatInterpolation');    
    $translateProvider.useSanitizeValueStrategy('escaped');
  }

})();

// test.module.js
(function() {
  'use strict';

  angular
    .module('testModule', ['applicationModule'])
    .config(['$translateProvider', '$translatePartialLoaderProvider', config])
    .run(['$httpBackend', run]);

  function config($translateProvider, $translatePartialLoaderProvider) {
    $translateProvider.useLoader('$translatePartialLoader', {
        urlTemplate: 'i18n/locale-en.json'
    });
    $translatePartialLoaderProvider.addPart('applicationModule');
  }

  function run($httpBackend) {
    $httpBackend.when('GET', 'i18n/locale-en.json').respond(200);
  }

})();


// someDirective.spec.js
describe("a3Dashboard", function() {
    beforeEach(module("testModule"))

    var element, $scope;
    beforeEach(inject(function($compile, $rootScope) {
        $scope = $rootScope;
        element = angular.element("<div>{{2 + 2}}</div>");
        $compile(element)($rootScope)
    }))

    it('should equal 4', function() {
      $scope.$digest();
      expect(element.html()).toBe("4");
    })

})
于 2015-04-20T05:58:24.627 に答える
0

これに対する2016年の答えは、jsonをテストに前処理し、翻訳がディレクティブで適切にテストされることです。

karma-ng-json2js-preprocessor を使用しています。すべての手順に従って karma.conf をセットアップし、テスト ファイルで関連ファイルをモジュールとして先頭に追加し、その情報を $translateProvider に設定します。

beforeEach(module('myApp', '/l10n/english-translation.json'));

// Mock translations for this template
beforeEach(module(function($translateProvider, englishTranslation) {
    $translateProvider.translations('en_us', englishTranslation);
    $translateProvider.useSanitizeValueStrategy(null);
    $translateProvider.preferredLanguage('en_us');
}));

プラグインによると、ファイル名を使用してキャメルケースのモジュール名を生成することに注意してください。モジュールの /lib 内の関数で遊ぶことができますが、基本的にはすべてのダッシュを削除しますが、camelCase の KEEPS アンダースコアは削除します。したがって、en_us は En_us になります。

また、そのファイルが GEt であることをテストに伝える必要があります。

    $httpBackend.expect('GET', '/l10n/english-translation.json').respond(200);
于 2016-11-14T02:50:26.270 に答える
0

これでテーブルに遅れましたが、カルマが次のエントリに従ってファイルを提供するように指定することで、これを回避しましたkarma.conf.js

files: [
    ...
    {pattern: 'scripts/i18n/*.json', included: false, served: true},
    ...
]
于 2016-04-11T20:08:15.353 に答える