typescript 使用导入的模块对 angular2 组件进行单元测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40268906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:57:44  来源:igfitidea点击:

Unit Testing angular2 component with imported module

angulartypescriptkarma-jasmineangular2-testingangular-material2

提问by George Edwards

I am trying to write a test on a component which uses angular-material2, but when I add it to my testModule declarations I get:

我正在尝试对使用 angular-material2 的组件编写测试,但是当我将它添加到我的 testModule 声明时,我得到:

Error: Template parse errors:
    'md-card-title' is not a known element:
    1. If 'md-card-title' is an Angular component, then verify that it is part of this module.
    2. If 'md-card-title' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.

Adding MaterialModule to the declarations throws `Error: Unexpected module 'MaterialModule' declared by the module

将 MaterialModule 添加到声明会抛出 `Error: Unexpected module 'MaterialModule' 由模块声明

DynamicTestModule' in config/spec-bundle.js (line 24994)

config/spec-bundle.js 中的 DynamicTestModule'(第 24994 行)

This is what my spec file looks like:

这是我的规范文件的样子:

  beforeEach(() => TestBed.configureTestingModule({
    declarations: [],
    providers: [
      { provide: DataService, useValue: mockDataService },
      { provide: ActivatedRoute, useClass: MockActivatedRoute },
      { provide: Router, useValue: mockRouter },
      CellViewComponent
    ]
  }));

adding CellViewComponentto the declarations array causes the error to throw.

添加CellViewComponent到声明数组会导致错误抛出。

回答by Paul Samsotha

When you use the TestBed.configureTestingModule, you're create a module from scratchfor the test environment. So what ever you would need in the real application for the CellViewComponentto work, you also need to configure it in the testing module.

当您使用 时TestBed.configureTestingModule,您将从头开始为测试环境创建一个模块。因此,您在实际应用程序中需要什么CellViewComponent才能工作,您还需要在测试模块中对其进行配置。

In your case, you're missing the Material card component. In the app you probably either imported the MaterialModuleor the MdCardModuleinto your AppModule. So you need to do the same in the testing module

在您的情况下,您缺少 Material 卡组件。在应用程序中,您可能将MaterialModule或导入MdCardModule到您的AppModule. 所以你需要在测试模块中做同样的事情

beforeEach(() => TestBed.configureTestingModule({
  imports: [ MaterialModule /* or MdCardModule */ ],
  declarations: [  CellViewComponent ],
  providers: [
    { provide: DataService, useValue: mockDataService },
    { provide: ActivatedRoute, useClass: MockActivatedRoute },
    { provide: Router, useValue: mockRouter },
  ]
}));

回答by smnbbrv

This is a real problem: you can mock everything but the imported component's selector.

这是一个真正的问题:您可以模拟除导入组件的选择器之外的所有内容。

There is an easy way. It allows to avoid importing the modules, instead you can just disable this kind of errors.

有一个简单的方法。它允许避免导入模块,相反,您可以禁用此类错误。

Just add this to your module:

只需将其添加到您的模块中:

import { NO_ERRORS_SCHEMA } from '@angular/core';

...

TestBed.configureTestingModule({
  schemas: [ NO_ERRORS_SCHEMA ],
  ...

Angular2 docs link

Angular2 文档链接

Yes, it won't help if you want to make integration (not isolated) tests, but it perfectly works for isolated ones.

是的,如果您想进行集成(非隔离)测试,它无济于事,但它完全适用于孤立的测试。

Still even if you would decide to import a module I think it might be more correct to import the mock module with all implemented selectors instead.

即使您决定导入一个模块,我认为导入带有所有已实现选择器的模拟模块可能更正确。

回答by Karl Johan Vallner

What I often do, when testing our Angular application components, is just import the parent module via reference. For most use cases, it is enough or close to enough and if you change the component, via adding new declarations or imports, then you do not need to worry about changing the test file, because the test file imports the parent module.

在测试我们的 Angular 应用程序组件时,我经常做的只是通过引用导入父模块。对于大多数用例,这已经足够或接近足够了,如果您通过添加新声明或导入来更改组件,那么您无需担心更改测试文件,因为测试文件会导入父模块。

I only ever change the module to import some external components for testing purposes, but this is rare.

我只更改模块以导入一些外部组件以进行测试,但这种情况很少见。

Regular test initialization pseudo code

常规测试初始化​​伪代码

beforeEach(() => TestBed.configureTestingModule({
    declarations: [
        ComponentA,
        ComponentB
    ],
    providers: [
        CellViewComponent
    ]
}));

let's say that this component is in a module. I put the declarations object into a variable for use in ParentModule and Testing simultaneously.

假设这个组件在一个模块中。我将声明对象放入一个变量中,以便同时在 ParentModule 和 Testing 中使用。

export var ParentModuleArgs = {
    declarations: [
        ComponentA,
        ComponentB
    ],
    providers: [
        CellViewComponent
    ]
  };

@NgModule(parentModuleArgs)
export class ParentModule {}

Then, instead of rewriting the whole Module array into the testing component and being very unDRY, I do.

然后,我没有将整个 Module 数组重写到测试组件中并且非常不干燥,而是这样做。

beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));

And if I need to add something, then we can just add it before configuring the test bed

如果我需要添加一些东西,那么我们可以在配置测试床之前添加它

let moduleArgs: NgModule = ParentModuleArgs;
moduleArgs.providers.push({provide: APP_BASE_HREF, useValue: '/'});

beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));