首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用templateUrl对AngularJS指令进行单元测试

使用templateUrl对AngularJS指令进行单元测试
EN

Stack Overflow用户
提问于 2013-03-05 10:26:15
回答 7查看 70.4K关注 0票数 122

使用AngularJS。

有一个指令。

指令定义templateUrl

指令需要单元测试。

目前使用Jasmine进行单元测试。

This推荐的代码如下:

代码语言:javascript
复制
describe('module: my.module', function () {
    beforeEach(module('my.module'));

    describe('my-directive directive', function () {
        var scope, $compile;
        beforeEach(inject(function (_$rootScope_, _$compile_, $injector) {
            scope = _$rootScope_;
            $compile = _$compile_;
            $httpBackend = $injector.get('$httpBackend');
            $httpBackend.whenGET('path/to/template.html').passThrough();
        }));

        describe('test', function () {
            var element;
            beforeEach(function () {
                element = $compile(
                    '<my-directive></my-directive>')(scope);
                angular.element(document.body).append(element);
            });

            afterEach(function () {
                element.remove();
            });

            it('test', function () {
                expect(element.html()).toBe('asdf');
            });

        });
    });
});

在Jasmine中运行代码。

获取错误:

代码语言:javascript
复制
TypeError: Object #<Object> has no method 'passThrough'

templateUrl需要按原样加载

无法使用respond

可能与ngMock的使用有关,而与ngMockE2E的使用无关。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2013-03-06 02:32:23

我最终所做的就是获取模板缓存并将视图放入其中。我无法控制不使用ngMock,事实证明:

代码语言:javascript
复制
beforeEach(inject(function(_$rootScope_, _$compile_, $templateCache) {
    $scope = _$rootScope_;
    $compile = _$compile_;
    $templateCache.put('path/to/template.html', '<div>Here goes the template</div>');
}));
票数 37
EN

Stack Overflow用户

发布于 2013-08-22 05:48:17

你说得对,它与ngMock有关。为每个角度测试自动加载ngMock模块,并初始化模拟$httpBackend以处理$http服务的任何使用,包括模板获取。模板系统试图通过$http加载模板,但它变成了对模拟的“意外请求”。

您需要的是一种无需使用$http就可以将模板预加载到$templateCache中的方法,这样当Angular请求它们时,它们就已经可用了。

首选解决方案: Karma

如果您正在使用Karma运行测试(您应该这样做),那么您可以配置它,以便使用ng-html2js预处理器为您加载模板。Ng-html2js读取您指定的HTML文件,并将其转换为预加载$templateCache的Angular模块。

步骤1:在karma.conf.js中启用并配置预处理器

代码语言:javascript
复制
// karma.conf.js

preprocessors: {
    "path/to/templates/**/*.html": ["ng-html2js"]
},

ngHtml2JsPreprocessor: {
    // If your build process changes the path to your templates,
    // use stripPrefix and prependPrefix to adjust it.
    stripPrefix: "source/path/to/templates/.*/",
    prependPrefix: "web/path/to/templates/",

    // the name of the Angular module to create
    moduleName: "my.templates"
},

如果您使用Yeoman构建您的应用程序,此配置将起作用

代码语言:javascript
复制
plugins: [ 
  'karma-phantomjs-launcher', 
  'karma-jasmine', 
  'karma-ng-html2js-preprocessor' 
], 

preprocessors: { 
  'app/views/*.html': ['ng-html2js'] 
}, 

ngHtml2JsPreprocessor: { 
  stripPrefix: 'app/', 
  moduleName: 'my.templates' 
},

第2步:在测试中使用该模块

代码语言:javascript
复制
// my-test.js

beforeEach(module("my.templates"));    // load new module containing templates

有关完整的示例,请查看此canonical example from Angular test guru Vojta Jina。它包括一个完整的设置: karma配置、模板和测试。

非因果报应解决方案

如果您出于某种原因不使用Karma (我在遗留应用程序中有一个不灵活的构建过程),并且只是在浏览器中测试,我发现您可以通过使用原始的XHR来实际获取模板并将其插入到$templateCache中来绕过ngMock对$httpBackend的接管。这种解决方案的灵活性要低得多,但它可以暂时完成工作。

代码语言:javascript
复制
// my-test.js

// Make template available to unit tests without Karma
//
// Disclaimer: Not using Karma may result in bad karma.
beforeEach(inject(function($templateCache) {
    var directiveTemplate = null;
    var req = new XMLHttpRequest();
    req.onload = function() {
        directiveTemplate = this.responseText;
    };
    // Note that the relative path may be different from your unit test HTML file.
    // Using `false` as the third parameter to open() makes the operation synchronous.
    // Gentle reminder that boolean parameters are not the best API choice.
    req.open("get", "../../partials/directiveTemplate.html", false);
    req.send();
    $templateCache.put("partials/directiveTemplate.html", directiveTemplate);
}));

不过,说真的。使用Karma。它需要一些工作来设置,但它允许您从命令行同时在多个浏览器中运行所有测试。因此,您可以将其作为持续集成系统的一部分,并且/或者您可以从编辑器中将其设置为快捷键。比alt-tab-refresh-ad-infinitum好多了。

票数 186
EN

Stack Overflow用户

发布于 2014-09-04 19:06:02

我的解决方案是:

test/karma-utils.js

代码语言:javascript
复制
function httpGetSync(filePath) {
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "/base/app/" + filePath, false);
  xhr.send();
  return xhr.responseText;
}

function preloadTemplate(path) {
  return inject(function ($templateCache) {
    var response = httpGetSync(path);
    $templateCache.put(path, response);
  });
}

karma.config.js

代码语言:javascript
复制
files: [
  //(...)
  'test/karma-utils.js',
  'test/mock/**/*.js',
  'test/spec/**/*.js'
],

测试:

代码语言:javascript
复制
'use strict';
describe('Directive: gowiliEvent', function () {
  // load the directive's module
  beforeEach(module('frontendSrcApp'));
  var element,
    scope;
  beforeEach(preloadTemplate('views/directives/event.html'));
  beforeEach(inject(function ($rootScope) {
    scope = $rootScope.$new();
  }));
  it('should exist', inject(function ($compile) {
    element = angular.element('<event></-event>');
    element = $compile(element)(scope);
    scope.$digest();
    expect(element.html()).toContain('div');
  }));
});
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15214760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档