Jasmine тестирует директивы AngularJS с помощью templateUrl


Я пишу директивные тесты для AngularJS с Jasmine и использую templateUrl с ними:https://gist.github.com/tanepiper/62bd10125e8408def5cc

однако, когда я запускаю тест, я получаю ошибку, включенную в суть:

Error: Unexpected request: GET views/currency-select.html

из того, что я прочитал в документах, я думал, что делаю это правильно, но это не так - что я здесь упускаю?

спасибо

8 69

8 ответов:

если вы используете ngMockE2E или ngMock:

все HTTP-запросы обрабатываются локально с использованием указанных вами правил и нет передаются на сервер. Поскольку шаблоны запрашиваются через HTTP, они также обрабатываются локально. Поскольку вы не указали, что делать, когда ваше приложение пытается подключиться к views/currency-select.html, Он говорит вам, что не знает, как с этим справиться. Вы можете легко сказать ngMockE2E, чтобы передать по шаблону запрос:

$httpBackend.whenGET('views/currency-select.html').passThrough();

помните, что вы также можете использовать регулярные выражения в свои маршруты, чтобы пройти через все шаблоны, если хотите.

документы обсуждают это более подробно:http://docs.angularjs.org/api/ngMockE2E.$httpBackend

в противном случае используйте это:

вам понадобится $injector для доступа к новому бэкэнду. Из связанных документов:

var $httpBackend;
beforeEach(inject(function($injector) {
  $httpBackend = $injector.get('$httpBackend');
  $httpBackend.whenGET('views/currency-select.html').respond(200, '');
}));

способ кармы заключается в динамической загрузке шаблона html в $templateCache. вы можете просто использовать html2js Karma pre-processor, как объяснил здесь

это сводится к добавлению шаблонов '.html ' к вашим файлам в конф.файл JS также препроцессоры= { - .html': 'html2js' };

и использовать

beforeEach(module('..'));

beforeEach(module('...html', '...html'));

в ваш тестовый файл js

если это модульный тест, у вас не будет доступа к $httpBackend.passthrough(). Это доступно только в ngMock2E2, для сквозного тестирования. Я согласен с ответами, с участием ng-html2js (раньше назывался html2js), но я хотел бы расширить их, чтобы обеспечить полное решение здесь.

чтобы отобразить вашу директиву, Angular использует $http.get() чтобы получить шаблон из templateUrl. Потому что это юнит-тестирование и angular-mocks загружается, angular-mocks перехватывает вызов $http.get() и дать вам Unexpected request: GET ошибка. Вы можете попытаться найти способы пройти мимо этого, но гораздо проще просто использовать angular $templateCache для предварительной загрузки шаблонов. Таким образом, $http.get() даже не будет проблемой.

вот что препроцессор ng-html2js сделать для вас. Чтобы заставить его работать, сначала установите его:

$ npm install karma-ng-html2js-preprocessor --save-dev

затем настройте его, добавив / обновив следующие поля в вашем karma.conf.js

{
    files: [
      //
      // all your other files
      //

      //your htmp templates, assuming they're all under the templates dir
      'templates/**/*.html'
    ],

    preprocessors: {
        //
        // your other preprocessors
        //

        //
        // tell karma to use the ng-html2js preprocessor
        "templates/**/*.html": "ng-html2js"
    },

    ngHtml2JsPreprocessor: {
        //
        // Make up a module name to contain your templates.
        // We will use this name in the jasmine test code.
        // For advanced configs, see https://github.com/karma-runner/karma-ng-html2js-preprocessor
        moduleName: 'test-templates',
    }
}

наконец, в вашем тестовом коде используйте test-templates модуль, который у вас есть просто создать. Просто добавьте test-templates к вызову модуля, который вы обычно делаете в beforeEach, например:

beforeEach(module('myapp', 'test-templates'));

это должно быть гладко отсюда. Для более глубокого изучения этого и других сценариев тестирования директив, проверьте этот пост

возможно, вы могли бы получить $templatecache из инжектора, а затем сделать что-то вроде

$templateCache.put("views/currency-select.html","<div.....>");

где вместо <div.....> вы бы положить свой шаблон.

после этого вы устанавливаете свою директиву, и она должна работать просто отлично!

Если это все еще не работает , используйте fiddler, чтобы увидеть содержимое JS-файла, динамически генерируемого процессором htmltojs, и проверить путь к файлу шаблона.

Это должно быть что-то вроде этого

angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
  $templateCache.put('app/templates/yourtemplate.html', 

в моем случае это было не то же самое, что у меня было в моей фактической директиве, которая вызывала проблему.

наличие templateURL точно так же во всех местах помогло мне пройти.

по запросу преобразование комментария в ответ.


для людей, которые хотят использовать ответ @Lior в старшина приложения:

иногда способ ссылки на шаблоны в конфигурации karma и, следовательно, - имена модулей, созданных ng-html2js не соответствует значениям, указанным как templateUrls в определениях директив.
Вам нужно будет настроить сгенерированные имена модулей, чтобы соответствовать templateUrls.
Это может быть полезно:

Это пример того, как проверить директиву, которая использует partial в качестве templateUrl

describe('with directive', function(){
  var scope,
    compile,
    element;

  beforeEach(module('myApp'));//myApp module

  beforeEach(inject(function($rootScope, $compile, $templateCache){
   scope = $rootScope.$new();
   compile = $compile;

   $templateCache.put('view/url.html',
     '<ul><li>{{ foo }}</li>' +
     '<li>{{ bar }}</li>' +
     '<li>{{ baz }}</li>' +
     '</ul>');
   scope.template = {
     url: 'view/url.html'
    };

   scope.foo = 'foo';
   scope.bar = 'bar';
   scope.baz = 'baz';
   scope.$digest();

   element = compile(angular.element(
    '<section>' +
      '<div ng-include="template.url" with="{foo : foo, bar : bar, baz : baz}"></div>' +
      '<div ng-include="template.url" with=""></div>' +
    '</section>'
     ))(scope);
   scope.$digest();

 }));

  it('should copy scope parameters to ngInclude partial', function(){
    var isolateScope = element.find('div').eq(0).scope();
    expect(isolateScope.foo).toBeDefined();
    expect(isolateScope.bar).toBeDefined();
    expect(isolateScope.baz).toBeDefined();
  })
});

Если вы используете jasmine-maven-plugin вместе с RequireJS вы можете использовать текст плагин загрузить шаблон в переменную, а затем поместить его в кэш шаблона.


define(['angular', 'text!path/to/template.html', 'angular-route', 'angular-mocks'], function(ng, directiveTemplate) {
    "use strict";

    describe('Directive TestSuite', function () {

        beforeEach(inject(function( $templateCache) {
            $templateCache.put("path/to/template.html", directiveTemplate);
        }));

    });
});