【问题标题】:How to Unit Test a Directive In Angular 2?如何在 Angular 2 中对指令进行单元测试?
【发布时间】:2016-07-25 18:01:24
【问题描述】:

问题:我希望能够在 Angular 2 中对指令进行单元测试,以确保它能够正确编译。

在 Angular 1 中,可以使用$compile(angular.element(myElement) 服务并在此之后调用$scope.$digest()。我特别希望能够在单元测试中做到这一点,这样我就可以在my-attr-directive 编译的代码中测试Angular 最终在<div my-attr-directive/> 上运行时。

约束:

【问题讨论】:

  • 您使用TestComponentBuilder,如划线的 SO 问题/答案中所示。在模板中使用指令的地方创建一个测试组件,然后从创建的测试组件实例中获取对该指令的引用。
  • 感谢您的回答。刚刚意识到你之前回答了这个问题!我认为当 TestComponentBuilder 移动到不同的包时,有一个关于删除对 TestComponentBuilder 的支持的评论,但我认为我在脑海中模糊了 SO 帖子。谢谢。我会关闭这个吗?

标签: javascript angularjs unit-testing angular angular2-directives


【解决方案1】:

使用 TestBed 测试编译指令

假设您有以下指令:

@Directive({
  selector: '[my-directive]',
})
class MyDirective {
  public directiveProperty = 'hi!';
}

你要做的是创建一个使用该指令的组件(它可以只是为了测试目的):

@Component({
  selector: 'my-test-component',
  template: ''
})
class TestComponent {}

现在您需要创建一个声明它们的模块:

describe('App', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [
        TestComponent,
        MyDirective
      ]
    });
  });

  // ...

});

您可以将模板(包含指令)添加到组件中,但可以通过覆盖测试中的模板来动态处理:

it('should be able to test directive', async(() => {
  TestBed.overrideComponent(TestComponent, {
    set: {
      template: '<div my-directive></div>'
    }
  });

  // ...      

}));

现在您可以尝试编译该组件,并使用By.directive 对其进行查询。最后,有可能使用injector 获取指令实例:

TestBed.compileComponents().then(() => {
  const fixture = TestBed.createComponent(TestComponent);
  const directiveEl = fixture.debugElement.query(By.directive(MyDirective));
  expect(directiveEl).not.toBeNull();

  const directiveInstance = directiveEl.injector.get(MyDirective);
  expect(directiveInstance.directiveProperty).toBe('hi!');
}); 

# 旧答案:

要测试一个指令,你需要用它创建一个假组件:

@Component({
  selector: 'test-cmp',
  directives: [MyAttrDirective],
  template: ''
})
class TestComponent {}

您可以在组件本身中添加模板,但可以通过覆盖测试中的模板来动态处理:

it('Should setup with conversation', inject([TestComponentBuilder], (testComponentBuilder: TestComponentBuilder) => {
    return testComponentBuilder
      .overrideTemplate(TestComponent, `<div my-attr-directive></div>`)
      .createAsync(TestComponent)
      .then((fixture: ComponentFixture<TestComponent>) => {
        fixture.detectChanges();
        const directiveEl = fixture.debugElement.query(By.css('[my-attr-directive]'));
        expect(directiveEl.nativeElement).toBeDefined();
      });
  }));

请注意,您可以测试指令呈现的内容,但我找不到以组件方式测试指令的方法(没有用于指令的 TestComponentBuilder)。

【讨论】:

  • 我收到错误:没有 DirectiveResolver 的提供者可能是什么原因?
  • 要使用By,您需要import { By } from '@angular/platform-browser';
  • difective 有@input 成员怎么样?,我有兴趣向这个控件添加单元测试:github.com/czeckd/angular-dual-listbox.. 但我不知道如何开始。
  • @Wojchieh - const directiveEl = fixture.debugElement.query(By.directive(MyDirective)); 真的很有帮助。很好的答案
  • 通过注入器访问指令实例:很棒 :) 我会记住的。谢谢
【解决方案2】:

我花了一段时间才找到一个好例子,Angular gitter 频道上的一个好人让我查看 Angular Material Design 2 存储库以获取示例。您可以找到指令测试示例here。这是 Material Design 2 的 tooltip 指令的测试文件。看起来您必须将其作为组件的一部分进行测试。

【讨论】:

  • 酷资源!感谢分享。不符合我作为JS文件问题的要求。
  • 纯JS很难找到任何资源。一个想法是获取材料设计存储库,对其进行编译并查看它生成的 .js 文件。我会惊讶于 Typescript 编译器生成的 JavaScript 代码的干净程度
  • 目前在纯JS中很难找到任何资源。一个想法是获取材料设计存储库,对其进行编译并查看它生成的 .js 文件。你会惊讶于 Typescript 编译器生成的 JavaScript 代码是多么干净
  • 这是一个很好的榜样。看起来回购已重新组织。工具提示规范现在是 here
猜你喜欢
  • 2017-08-08
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 2016-04-09
  • 2018-01-05
  • 2019-01-21
  • 1970-01-01
  • 2019-11-02
相关资源
最近更新 更多