【问题标题】:Trouble unit-testing directives that use templateUrl麻烦使用 templateUrl 的单元测试指令
【发布时间】:2014-05-26 14:00:43
【问题描述】:

我在使用 templateUrl 的单元测试指令时遇到问题。

有这个很棒的关于 AngularJS 测试的教程 [1],它甚至还有一个与之配套的 Github 存储库 [2]

所以我将它分叉 [3] 并进行了以下更改:

directives.js 我创建了两个新指令:

.directive('helloWorld', function() {
    return {
      restrict: 'E',
      replace: true,
      scope:{},
      template: '<div>hello world!</div>',
      controller: ['$scope', function ($scope) {}]
    }
})

.directive('helloWorld2', function() {
    return {
      restrict: 'E',
      replace: true,
      scope:{},
      templateUrl: 'mytemplate.html',
      controller: ['$scope', function ($scope) {}]
    }
})

我更改了test/unit/directives/directivesSpecs.js,以便将模板加载到 $templateCache 中,然后为新指令添加了另外两个测试:

//
// test/unit/directives/directivesSpec.js
//
describe("Unit: Testing Directives", function() {

  var $compile, $rootScope, $templateCache;

  beforeEach(angular.mock.module('App'));

  beforeEach(inject(
    ['$compile','$rootScope', '$templateCache', function($c, $r, $tc) {
      $compile = $c;
      $rootScope = $r;

      //Added $templateCache and mytemplate
      $templateCache = $tc;
      $templateCache.put('mytemplate.html', '<div>hello world 2!</div>');
    }]
  ));

  //This was already here
  it("should display the welcome text properly", function() {
    var element = $compile('<div data-app-welcome>User</div>')($rootScope);
    expect(element.html()).to.match(/Welcome/i);
  });


  //Added this test - it passes
  it("should render inline templates", function() {
    var element = $compile('<hello-world></hello-world>')($rootScope);
    expect(element.text()).equal("hello world!");
  });

  //Added this test - it fails
  it("should render cached templates", function() {
    var element = $compile('<hello-world2></hello-world2>')($rootScope);
    expect(element.text()).equal("hello world 2!");
  });

});

最后一次测试失败,因为 Angular 不会像它应该的那样编译模板。

$ grunt test:unit
Running "karma:unit" (karma) task
INFO [karma]: Karma v0.10.10 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 35.0.1916 (Linux)]: Connected on socket ChISVr0ZABZ1fusdyv3m
Chrome 35.0.1916 (Linux) Unit: Testing Directives should render cached templates FAILED
    expected '' to equal 'hello world 2!'
    AssertionError: expected '' to equal 'hello world 2!'
Chrome 35.0.1916 (Linux): Executed 18 of 18 (1 FAILED) (0.441 secs / 0.116 secs)
Warning: Task "karma:unit" failed. Use --force to continue.

Aborted due to warnings.

我很确定这应该有效。 至少,它与@SleepyMurth 在[4] 上提出的解决方案非常相似。

但我觉得我已经达到了理解我目前对 AngularJS 的了解出了什么问题的极限。

帮助! :-)

[1]http://www.yearofmoo.com/2013/01/full-spectrum-testing-with-angularjs-and-karma.html

[2]https://github.com/yearofmoo-articles/AngularJS-Testing-Article/

[3]https://github.com/tonylampada/AngularJS-Testing-Article

[4]Unit Testing AngularJS directive with templateUrl

【问题讨论】:

  • 那么,element.text() 返回什么?
  • 抱歉,我会更新问题以包含该问题(它是一个空字符串)

标签: javascript angularjs unit-testing gruntjs karma-runner


【解决方案1】:

问题

当指定templateUrl 时,使用$http 获取模板(即使对于缓存模板,$http$templateCache 提供服务)。出于这个原因,$http 的 promise 需要一个 $digest 循环才能使用模板内容解析并由指令处理。


解决办法

由于 Promise 在 $digest 周期内得到解决(并且由于我们处于“Angular 上下文”之外),因此我们需要在评估我们的断言之前手动调用 $rootScope.$digest()
因此,最后一个测试应该这样修改:

it("should render cached templates", function() {
    var element = $compile('<hello-world2></hello-world2>')($rootScope);
    $rootScope.$digest();   // <-- manually force a $digest cycle
    expect(element.text()).toBe(tmplText);
});

另请参阅此short demo

【讨论】:

  • 我喜欢这个网站!给先生点个赞。非常感谢!
  • 我只想回到这里,重申我对这个答案的速度和质量印象深刻。哎呀! :-)
  • 我已经设置了模板缓存,编译了我的元素,消化了它编译到的范围,但是指令元素没有被模板替换。 =( 我没有收到任何错误,只是在单元测试期间没有编译它。
  • @FlavorScape:用相关代码和(如果可能)复制小提琴或 plunkr 发布问题。
  • 我可以做一个 plunkr,但我的相关代码几乎是一样的。除非它包含一个 ng-repeat...只有一个注释掉的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
相关资源
最近更新 更多