【问题标题】:Angular 1.5 unit testing component while ignoring child componentsAngular 1.5 单元测试组件同时忽略子组件
【发布时间】:2017-05-05 16:53:03
【问题描述】:

我正在尝试为 Angular 1.5 中的组件编写单元测试。我想对该组件及其 dom 节点进行单元测试。该组件包含一个相当复杂的子组件。

我的目标是在不编译子组件的情况下对外部组件进行单元测试。

因为我也想测试 DOM,所以在这个测试中使用 $componentController 是不够的。

这是我想要实现的一个简短示例:

组件代码:

angular.module('app').component('myComponent', {
  bindings: {
    username: '<',
  },
  template: `
    <span>{{ $ctrl.username }}</span>
    <my-complex-component />
  `
  controller: function () {}
});

我的组件的单元测试:

it('my-component should render username', function () {
  var template = '<my-component username="username"></my-component>',
    element,
    scope,
    date;

  scope = $rootScope.$new();
  scope.username = 'John';

  element = $compile(template)(scope);
  scope.$digest();

  username = element.find('span');
  expect(username.text()).to.be.equal('John');
});

my-complex-component 不应被实例化。它应该按原样抵抗模板。在单元测试中创建元素应该会导致

<span>John</span>
<my-complex-component />

有什么办法吗?

【问题讨论】:

  • 据我所知,它完全符合您的预期。当您编译组件时,它不会编译内部组件。看看console.log(element)
  • 不幸的是,my-component 和 my-complex-component 都位于模块 app.由于我必须调用 angular.mock.module('app') 来模拟模块,它会加载两个组件并尝试编译 my-complex-component。
  • 你可以尝试模拟my-complex-component。请参阅 this answer 模拟指令,但请改用 $compileProvider.component

标签: angularjs unit-testing mocking components


【解决方案1】:

Here is a very good explanation 如何在不渲染当前组件下的整个树的情况下测试组件。

你想要的就叫

浅渲染(避免渲染子组件的整个模板)

Angular 1.5 并没有提供开箱即用的功能。

如果您查看上面的链接,Wojciech Zawistowski 将展示如何使用下面的帮助程序来实现浅层渲染。

export function componentSpyOn(name) {
  function componentSpy($provide) {
    componentSpy.bindings = [];

    $provide.decorator(name + 'Directive', ($delegate) => {
      let component = $delegate[0];

      component.template = '';
      component.controller = class {
        constructor() {
          componentSpy.bindings.push(this);
        }
      };

      return $delegate;
    });
  }

  return componentSpy;
}

【讨论】:

    【解决方案2】:

    您可以通过使用 $compileProvider.directive 覆盖您的子组件来做到这一点,即使它是一个组件,因为组件是一种特殊的指令。

    在您的单元测试中,向编译器注册一个与您的子组件同名的新组件,但不提供控制器并将模板设置为空字符串。这将导致组件没有任何逻辑/复杂性:

    beforeEach(module('app', function($compileProvider){
        $compileProvider.directive('myComplexComponent', function (){
            return {
                priority: 9999,
                terminal: true,
                template: ''
            };
        });
    }));
    

    因此,生成的 html 将最适合您的外部组件单元测试:

    <span>John</span>    
    

    【讨论】:

      【解决方案3】:

      有一种方法可以对其进行测试,但最终结果将是:

      <span>John</span>
      <ng-transclude></ng-transclude>
      

      组件代码:

        angular.module('app').component('myComponent', {
        enter code herebindings: {
          username: '<',
        },
        template: `
          <span>{{ $ctrl.username }}</span>
          <ng-transclude></ng-transclude>
        `,
        transclude: true, // Added property
        controller: function () {}
      });
      

      如您所见,我删除了&lt;my-complex-component&gt;,并添加了&lt;ng-transclude&gt;

      也就是说你可以从外部添加你的信息,它会被注入到ng-transclude的位置。

      例如,在您的主 html 中:

      <my-component>
          <my-complex-component></my-complex-component>
      </my-component>
      

      将从一开始就以您想要的方式在 DOM 中:

      <span>John</span>
      <my-complex-component></my-complex-component>
      

      之后你的测试应该可以工作了。

      我希望这个答案是您想要的,并且对您有所帮助。

      【讨论】:

      • 我不确定更改组件的标记是否是正确的方法。它使标记不那么直观。另外,如果有多个子组件怎么办?
      • 我认为如果您希望您的组件更具可测试性,这是一种更好的方法,通过这种方式,您可以在主组件中放置尽可能多的组件,而不会破坏您的测试。这样,当事情开始出现问题时,您可以看到您的主要组件仍然工作(或不工作)。
      【解决方案4】:

      您可以在单元测试中用一个空模块覆盖子组件模块定义。

      // Unit Test Parent component
      describe('Unit Testing: myComponent Component', () => { 
      
        beforeEach(() => {
          // overwrite module
          angular.module('myComplexComponent', []);
          module('myComponent');
        });
      });
      

      现在父组件仍然会尝试注入和渲染子组件,但是由于这个子组件完全是空的,所以什么都不会发生。

      【讨论】:

        猜你喜欢
        • 2017-08-17
        • 1970-01-01
        • 2021-01-05
        • 2016-10-07
        • 1970-01-01
        • 2019-07-04
        • 2017-09-15
        • 1970-01-01
        • 2018-01-01
        相关资源
        最近更新 更多