如何使用angular-translate进行单元测试

bin*_*bin 40 unit-testing mocking angularjs yeoman karma-runner

我从这里使用角度翻译(http://pascalprecht.github.io/angular-translate/)并且它工作正常,但它打破了我的控制器的单元测试错误:

Unexpected request: GET scripts/i18n/locale-en.json
Run Code Online (Sandbox Code Playgroud)

我不明白为什么?

我使用自耕农和业力考验.

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

})();
Run Code Online (Sandbox Code Playgroud)

configTranslate.js:

'use strict';

(function() {

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

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

        $translateProvider.preferredLanguage('en');

      }]);

})();
Run Code Online (Sandbox Code Playgroud)

karma.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',

  ...

];
Run Code Online (Sandbox Code Playgroud)

控制器测试:

'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(...);

  ...

});
Run Code Online (Sandbox Code Playgroud)

如果我在测试控制器中添加这个,产品相同的错误:

httpMock.when('GET', 'scripts/i18n/locale-en.json').respond(200);
httpMock.flush();
Run Code Online (Sandbox Code Playgroud)

要么

httpMock.when('GET', 'scripts/i18n/locale-en.json').passThrough();
httpMock.flush();
Run Code Online (Sandbox Code Playgroud)

我发现这篇文章如何在App Config中初始化Angular Translate测试控制器?但没有帮助我:/

我在我的测试中广泛使用$ httpBackend并且它工作正常,但在这种情况下它是无效的.如果我评论该行:

$translateProvider.preferredLanguage('en');
Run Code Online (Sandbox Code Playgroud)

显然是一个错误,如果我添加运行时(在我的控制器中)

$translate.uses(local);
Run Code Online (Sandbox Code Playgroud)

我最终得到了同样的错误?

所以我转向翻译配置(configTranslate.js)或在运行时是相同的结果:

Unexpected request: GET scripts/i18n/locale-en.json
Run Code Online (Sandbox Code Playgroud)

这是我在"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);
Run Code Online (Sandbox Code Playgroud)

最后

httpMock.flush();
Run Code Online (Sandbox Code Playgroud)

我也尝试了$申请

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

没有任何反应,仍然这个错误让我发疯

如果您有任何建议

nol*_*mit 28

这是一个已知问题,请按照此处的文档:单元测试角度

解决方案

不幸的是,这个问题是由角度平移的设计引起的.为了解决这些错误,我们所能做的就是覆盖我们的测试套件中的模块配置,它根本不使用异步加载器.当没有异步加载器时,没有XHR,因此没有错误.

那么我们如何在运行时为我们的测试套件覆盖我们的模块配置呢?在实例化角度模块时,我们总是可以应用作为配置函数执行的内联函数.此配置功能可用于覆盖模块配置,因为我们可以访问所有提供程序.

使用$ provide提供程序,我们可以构建一个自定义加载器工厂,然后应该使用它来代替静态文件加载器.

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

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

  $translateProvider.useLoader('customLoader');

}));
Run Code Online (Sandbox Code Playgroud)

请在上面提供的链接中阅读更多内容.


Ere*_*hen 15

我们采用了在单元测试中忽略翻译加载器的方法,而不是被迫修改每个spec文件.

一种方法是将加载器配置分离到单独的文件,然后在业力中将其排除.

例如,您可以创建一个文件app-i18n-loader.js(所有其他模块配置都在不同的文件中进行):

    angular
    .module('myApp')
    .config(loaderConfig);

loaderConfig.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];

function loaderConfig($translateProvider, $translatePartialLoaderProvider) {

    $translateProvider.useLoader('$translatePartialLoader', {
        urlTemplate: 'assets/i18n/{part}/{lang}.json'
    });

    $translatePartialLoaderProvider.addPart('myApp');
}
Run Code Online (Sandbox Code Playgroud)

在你的karma.conf.js中排除文件:

        files: [
        'bower_components/angular/angular.js',
        'bower_components/angular-mocks/angular-mocks.js',
        //...
        'bower_components/angular-translate/angular-translate.js',
        'bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',
        'app/**/*.mdl.js',
        'app/**/*.js'
    ],

    exclude: [
        'app/app-i18n-loader.js'
    ],
Run Code Online (Sandbox Code Playgroud)

(注意:答案编辑为不需要grunt/gulp的解决方案).


hug*_*ige 12

我想要一个解决方案,

  1. 这不是太hacky
  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 () {
    };
}));
Run Code Online (Sandbox Code Playgroud)

假设您不需要单元测试的实际翻译,这很有用.只需将beforeEach放在全局级别,最好放在test文件夹中的自己的文件中.它将在每次其他测试之前执行.


Mat*_*nen 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
}
Run Code Online (Sandbox Code Playgroud)

请参阅Angular 文档中的示例