71

我正在用 Jasmine 为 AngularJS 编写指令测试,并与它们一起使用 templateUrl:https ://gist.github.com/tanepiper/62bd10125e8408def5cc

但是,当我运行测试时,我得到了要点中包含的错误:

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

从我在文档中读到的内容来看,我认为我这样做是正确的,但似乎并非如此 - 我在这里错过了什么?

谢谢

4

8 回答 8

70

如果您使用的是 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, '');
}));
于 2013-02-07T21:45:55.653 回答
20

Karma 方式是将模板 html 动态加载到 $templateCache 中。您可以只使用 html2js 业力预处理器,如此处所述

这归结为将模板“ .html”添加到 conf.js 文件中的文件以及预处理器 = { ' .html': 'html2js' };

并使用

beforeEach(module('..'));

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

进入你的 js 测试文件

于 2013-05-10T17:51:03.267 回答
6

如果这是一个单元测试,您将无法访问$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'));

从这里开始应该一帆风顺。要更深入地了解这个和其他指令测试场景,请查看这篇文章

于 2016-06-29T07:18:53.040 回答
5

您也许可以$templatecache从注射器中获取,然后执行类似的操作

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

代替<div.....>您将模板放在哪里。

之后你设置你的指令,它应该工作得很好!

于 2013-02-07T22:48:41.827 回答
4

如果还是不行,用fiddler查看htmltojs处理器动态生成的js文件的内容,检查模板文件的路径。

它应该是这样的

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

就我而言,它与导致问题的实际指令中的不同。

在所有地方都有完全相同的 templateURL 让我通过了。

于 2013-06-11T05:11:01.630 回答
4

根据要求,将评论转换为答案。


对于想要在Yeoman应用程序中使用 @Lior 答案的人:

有时在 karma config 中引用模板的方式以及因此产生的模块名称与指令定义中ng-html2js指定为 s 的值不匹配。 您将需要调整生成的模块名称以匹配s。 这些可能会有所帮助:templateUrl
templateUrl

于 2014-06-25T03:52:06.563 回答
2

这是如何测试使用部分作为 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();
  })
});
于 2014-07-21T05:59:32.417 回答
0

如果您将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);
        }));

    });
});
于 2014-05-15T11:11:35.587 回答