我正在使用Jasmine为AngularJS编写指令测试,并使用templateUrl:https://gist.github.com/tanepiper/62bd10125e8408def5cc
然而,当我运行测试时,我得到了要点中包含的错误:
Error: Unexpected request: GET views/currency-select.html
从我在文档中看到的内容我认为我正确地做到了这一点,但似乎并非如此 - 我在这里缺少什么?
由于
答案 0 :(得分:70)
所有 HTTP请求,并将 none 传递给服务器。由于模板是通过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, '');
}));
答案 1 :(得分:20)
Karma方式是将模板html动态加载到$ templateCache中。您可以使用html2js karma预处理器,如here
所述这归结为将模板“ .html”添加到conf.js文件中的文件中 同样 预处理器= { ' .html':'html2js' };
并使用
beforeEach(module('..'));
beforeEach(module('...html', '...html'));
进入你的js测试文件
答案 2 :(得分:6)
如果这是单元测试,则您无法访问$httpBackend.passthrough()
。这只适用于ngMock2E2,用于端到端测试。我同意涉及ng-html2js
(以前称为html2js)的答案,但我想扩展它们以提供完整的解决方案。
为了呈现您的指令,Angular使用$http.get()
从templateUrl
获取您的模板。由于这是单元测试并且已加载angular-mocks
,因此angular-mocks
会拦截对$http.get()
的调用,并向您显示Unexpected request: GET
错误。您可以尝试通过此方法找到方法,但只使用角度$templateCache
来预加载模板要简单得多。这样,$http.get()
甚至不会成为一个问题。
这是ng-html2js preprocessor为你做的事情。要使它工作,首先安装它:
$ 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'));
这应该是从这里开始顺利航行。要更深入地了解此指令和其他指令测试方案,请查看this post
答案 3 :(得分:5)
您可以从进样器获取$templatecache
,然后执行类似
$templateCache.put("views/currency-select.html","<div.....>");
代替<div.....>
,您将放置模板。
之后你设置了你的指令,它应该可以正常工作!
答案 4 :(得分:4)
如果仍然无效,请使用fiddler查看htmltojs处理器动态生成的js文件的内容,并检查模板文件的路径。
它应该是这样的
angular.module('app/templates/yourtemplate.html', []).run(function($templateCache) {
$templateCache.put('app/templates/yourtemplate.html',
在我的情况下,它与我导致问题的实际指令中的情况不一样。
让templateURL在所有地方完全相同,让我度过难关。
答案 5 :(得分:4)
根据要求,将评论转换为答案。
对于想要在 Yeoman 应用中使用@Lior的答案的人:
有时在karma配置中引用模板的方式因此 - ng-html2js
生成的模块的名称与指令定义中指定为templateUrl
的值不匹配。
您需要调整生成的模块名称以匹配templateUrl
s
这些可能会有所帮助:
答案 6 :(得分:2)
这是如何测试使用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();
})
});
答案 7 :(得分:0)
如果您将jasmine-maven-plugin与RequireJS一起使用,则可以使用text plugin将模板内容加载到变量中,然后将其放入模板缓存中。
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);
}));
});
});