programing

angular-translate를 사용한 유닛 테스트 방법

fastcode 2023. 4. 5. 22:17
반응형

angular-translate를 사용한 유닛 테스트 방법

http://pascalprecht.github.io/angular-translate/) 에서 각도 변환을 사용하고 있습니다만, 정상적으로 동작하고 있습니다만, 컨트롤러의 유닛 테스트가 고장났습니다.에러:

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

이해가 안 가 왜?

나는 업보로 요먼과 테스트를 한다.

app.filename:

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

      }]);

})();

karma.conf.displays:

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

앱 구성에서 Angular Translate를 사용하여 컨트롤러를 테스트하려면 어떻게 해야 합니까?도움이 되지 않았다:/

테스트에서 $httpBackend를 광범위하게 사용하고 있으며 정상적으로 동작하지만 이 경우 효과가 없습니다.행을 코멘트하면:

$translateProvider.preferredLanguage('en');

(컨트롤러에서) 런타임에 추가하면 명백한 오류입니다.

$translate.uses(local);

같은 에러가 발생한다고요?

변환 설정(configTranslate.js)을 실행해도 같은 결과가 됩니다.

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

다음은 테스트한 구문입니다. "before Every"(inject(function)(...)" 중 하나입니다.});"

또는 테스트에서 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();

나도 $어플리케이션을 시도했다.

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

아무 일도 일어나지 않는다. 여전히 이 오류는 나를 미치게 한다.

제안사항이 있으시면

이미 알려진 문제이므로 다음 문서를 따르십시오.유닛 테스트 각도

해결 방법

안타깝게도 이 문제는 각도 변환 설계로 인해 발생합니다.이러한 에러를 회피하려면 테스트 스위트의 모듈 설정을 덮어쓰기만 하면 됩니다.이것에 의해 비동기 로더가 전혀 사용되지 않게 됩니다.비동기 로더가 없는 경우 XHR이 없으므로 오류가 발생하지 않습니다.

그러면 테스트 스위트 실행 시 모듈 구성을 덮어쓰려면 어떻게 해야 할까요?각도 모듈을 인스턴스화할 때 구성 함수로 실행되는 인라인 함수를 항상 적용할 수 있습니다.모든 공급자에 액세스할 수 있으므로 이 구성 기능을 사용하여 모듈 구성을 덮어쓸 수 있습니다.

$provider 공급자를 사용하여 커스텀 로더 팩토리를 구축할 수 있습니다.이 팩토리는 정적 파일 로더 대신 사용해야 합니다.

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

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

  $translateProvider.useLoader('customLoader');

}));

자세한 내용은 위의 링크를 참조하십시오.

유닛 테스트에서는 각 스펙 파일을 강제로 수정하지 않고 번역 로더를 무시하는 방법을 사용했습니다.

로더 설정을 다른 파일로 분리한 후 카르마로 제외하는 방법도 있습니다.

예를 들어 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');
}

또한 카르마.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'
    ],

(주: grunt/gulp이 필요없는 용액으로 편집한 답변)

난 해결책을 원했어

  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 () {
    };
}));

유닛 테스트에 실제 번역이 필요하지 않다고 가정하면 이 방법은 매우 효과적입니다.beforeEvery를 글로벌 레벨로, 가능하면 테스트 폴더 내의 자체 파일에 넣습니다.그럼 다른 모든 테스트보다 먼저 실행됩니다.

나는 이 문제를 견인기 테스트에서 만났다.저의 해결책은 다음과 같은 번역을 조롱하는 것이었습니다.

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

언어 파일은 다운로드되지 않고 문자열은 번역되지 않으며 사양의 문자열 키와 대조하여 테스트합니다.

expect(element(by.css('#title')).getText()).toEqual('TITLE_TEXT');

테스트 방법을 사용해 보십시오.

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 문서의 예를 참조하십시오.

https://github.com/PascalPrecht/angular-translate/blob/master/test/unit/service/loader-static-files.spec.js 를 참조해 주세요.

유닛하는 것이 ).즉, 에 「」를 수 .$translateProvider.translations()요? 로딩 왜요? 각도 변환 프로젝트의 일부인 원격 로딩 기능을 테스트할 필요가 없기 때문입니다.

어느 솔루션도 효과가 없었지만, 다음과 같은 솔루션을 도입했습니다.

을 1) 을 사용해야 .scope.$apply())를 다루어야 $apply() 접근 않습니다)))))) 、 ) 、 ) 、 ) 、 ) 、 ) 、 ) 、 ) )))))))) ) 。$translateProvider.translations()방법, 플러그인을 사용하여 JSON 파일을 로드합니다.

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

2)가 2) 에 하고 있는 $translate플러그인을 사용하여 JSON 파일을 로드하고 결합할 수 있습니다.$httpBackend로케일 파일을 로드합니다.

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에러입니다.

나는 $translate에 간단한 모의 서비스를 만들었다.

$translate=function (translation) {
    return {
      then: function (callback) {
        var translated={};
        translation.map(function (transl) {
          translated[transl]=transl;
        });
        return callback(translated);
      }
    }
  };

사용 예: https://gist.github.com/dam1/5858bdcabb89effca457

저는 이 패턴을 사용합니다.

  • Application Module은 표준 각도 변환 구성을 설정합니다.
  • 테스트 코드 로드 '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");
    })

})

이 문제에 대한 논의는 늦었지만, 카르마가 단순히 이 엔트리에 따라 파일을 제공한다는 것을 명시함으로써 이 문제를 해결했습니다.karma.conf.js:

files: [
    ...
    {pattern: 'scripts/i18n/*.json', included: false, served: true},
    ...
]

이에 대한 2016년 답변은 json을 테스트에 사전 처리하고 지시문에 따라 적절하게 번역 작업을 테스트하는 것입니다.

Karma-ng-json2js-프리프로세서를 사용합니다.모든 절차에 따라 카르마.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 내의 함수를 사용할 수 있지만 기본적으로 모든 대시를 제거하고 KEEP 밑줄을 camelCase로 표시합니다.en_us는 en_us가 됩니다.

또한 테스트에 해당 파일을 GET로 상정하고 있음을 알려야 합니다.

    $httpBackend.expect('GET', '/l10n/english-translation.json').respond(200);

언급URL : https://stackoverflow.com/questions/18876290/how-do-unit-test-with-angular-translate

반응형