在Angular单元测试中,如何模拟整个组件,而不仅仅是一个类?

huangapple go评论74阅读模式
英文:

In an Angular Unit Test, how can I mock an entire component, instead of just a class?

问题

我试图对使用子组件的组件进行单元测试。我需要模拟子组件,因为子组件使用CanvasJS来显示图表,而CanvasJS与Jest单元测试不兼容。

目前,我的规范文件中如下所示使用了这个:

```javascript
import { SubComponent } from '../shared/components/sub/sub.component';
import { SubComponentMock } from '../shared/mocks/component/SubComponentMocks';
...

const createComponent = createComponentFactory({
  component: PageComponent,
  declarations: [ViewComponent],
  imports: [],
  providers: [
    { provide: SubComponent, useClass: SubComponentMock },
  ],
});

beforeEach(() => {
  jest.restoreAllMocks();
  spectator = createComponent();
});

it('should create', () => {
  expect(spectator.component).toBeTruthy();
});

我的SubComponentMocks文件包含一个名为 SubComponentMock 的类,该类具有与SubComponent中的函数相同的函数。我遇到了以下错误:

从 'sub.component.ts' 无法找到模块 'canvasjs'

难道模拟不应该导致测试根本不尝试查找该模块吗?它不应该在sub.component.ts中执行任何操作,它应该只访问SubComponentMocks。是否有一种方法可以对整个组件进行模拟,以便测试不会尝试查找canvasjs模块?


<details>
<summary>英文:</summary>

I&#39;m trying to unit test a component that is using a subcomponent. I need to mock the subcomponent because the subcomponent uses CanvasJS to display plots, which doesn&#39;t work well with Jest Unit Tests.

Right now, this is being used in my spec file as seen below:

import { SubComponent } from '../shared/components/sub/sub.component';
import { SubComponentMock } from '../shared/mocks/component/SubComponentMocks';
...

const createComponent = createComponentFactory({
component: PageComponent,
declarations: [ViewComponent],
imports: [],
providers: [
{ provide: SubComponent, useClass: SubComponentMock },
],
});

beforeEach(() => {
jest.restoreAllMocks();
spectator = createComponent();
});

it('should create', () => {
expect(spectator.component).toBeTruthy();
});


My SubComponentMocks file contains a class ```SubComponentMock ``` which has functions that are in SubComponent. I am getting the following error:

```Cannot find module &#39;canvasjs&#39; from &#39;sub.component.ts&#39;```

Shouldn&#39;t the mock cause the test to not try to find that module at all? It shouldn&#39;t be doing anything in sub.component.ts, it should only be accessing SubComponentMocks. Is there a way for the whole component to be mocked so the test doesn&#39;t try to find the canvasjs module?

</details>


# 答案1
**得分**: 1

在你的规范中添加模拟子组件,如下所示:

```typescript
@Component({
  selector: 'sub'
})
class MockComponent {
  mockProperty <----- 正在使用的属性
}

在创建组件中执行以下操作:

const createComponent = createComponentFactory({
  component: PageComponent,
  declarations: [ViewComponent, MockComponent],
  imports: [],
  providers: [],
});
英文:

add mock subcomponent in your spec like this :-

 @Component({
    selector:&#39;sub&#39;
    })
    class MockComponent{
    mockProperty &lt;----- which being used
    }

and in create component do this :-

const createComponent = createComponentFactory({
    component: PageComponent,
    declarations: [ViewComponent,MockComponent],
    imports: [],
    providers: [],
  });

答案2

得分: -1

I am familiar with Karma and Jasmine but I assume Jest behaves the same in this regard.

In your use case, I would take advantage of the NO_ERRORS_SCHEMA. This basically tells Angular, if you see an element in the HTML that you don't recognize, don't worry about it.

import { NO_ERRORS_SCHEMA } from '@angular/core';
......
const createComponent = createComponentFactory({
    component: PageComponent,
    declarations: [ViewComponent],
    imports: [],
    schemas: [NO_ERRORS_SCHEMA],
  });

The way you are mocking the component right now is how you would mock a service.

Also, Aditya's way might work too but I find NO_ERRORS_SCHEMA to be better (less work if you don't care about the child components in your unit tests).

Also, look into overrideComponent and overrideModule but this maybe only if you're using Angular's methodology for testing.

===== edit ==========

Never mind, it seems like you're using ngneat for testing. I would leverage componentMocks property then, not schema.

英文:

I am familiar with Karma and Jasmine but I assume Jest behaves the same in this regard.

In your use case, I would take advantage of the NO_ERRORS_SCHEMA. This basically tells Angular, if you see an element in the HTML that you don't recognize, don't worry about it.

import { NO_ERRORS_SCHEMA } from &#39;@angular/core&#39;;
......
const createComponent = createComponentFactory({
    component: PageComponent,
    declarations: [ViewComponent],
    imports: [],
    schemas: [NO_ERRORS_SCHEMA],
  });

The way you are mocking the component right now is how you would mock a service.

Also, Aditya's way might work too but I find NO_ERRORS_SCHEMA to be better (less work if you don't care about the child components in your unit tests).

Also, look into overrideComponent and overrideModule but this maybe only if you're using Angular's methodology for testing.

===== edit ==========

Never mind, it seems like you're using ngneat for testing. I would leverage componentMocks property then, not schema.

huangapple
  • 本文由 发表于 2020年1月7日 00:13:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615397.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定