测试组件时如何模拟管道
Posted
技术标签:
【中文标题】测试组件时如何模拟管道【英文标题】:How to mock Pipe when testing Component 【发布时间】:2017-01-10 14:53:44 【问题描述】:目前我正在覆盖提供者以使用这样的模拟服务:
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) =>
tcb.overrideProviders(AddFieldToObjectDropdownComponent,
[
provide(ServiceA, useClass: MockServiceA )),
provide(ServiceB, useClass: MockServiceB ))
])
...
我想对组件使用的管道做同样的事情。我试过了,provide(PipeA, useClass: MockPipeA )
和 provide(PipeA, useValue: new MockPipeA() )
但都没有工作。
【问题讨论】:
当您在 4 个月内没有任何答案时,这并不乐观。你有想过这个吗? @coblr 不,不幸的是,这对我来说不是一个高优先级问题,但我很快会使用新的测试 API 再次尝试,也许现在有一个解决方法。 有什么解决办法吗?我试图不声明原始管道,而是创建一个模拟管道并声明它。但不知何故,管道渲染结果总是显示一个空字符串 '' @harunurhan 你只需要模板中的管道吗? 现在是 2019 年,仍然发生在我身上 :( 我期待“提供”的事情能够奏效。 【参考方案1】:基于 @shohrukh 的回答,以下代码为您提供了一个可在 Angular 11/12 中工作的可重复使用的模拟管道:
import Pipe, PipeTransform from '@angular/core';
export function mockPipe(name: string): Pipe
const metadata: Pipe =
name
;
return Pipe(metadata)(
class MockPipe implements PipeTransform
transform()
);
然后在你的测试中使用它:
TestBed.configureTestingModule(
declarations: [
MyComponent,
mockPipe('myPipe')
],
...
).compileComponents();
【讨论】:
【参考方案2】:一种可能性是使用ng-mocks library 并像这样使用它:
TestBed.configureTestingModule(
declarations: [
TestedComponent,
MockPipe(ActualPipe, (...args) => args[0]),
]
).compileComponents();
MockPipe 的第二个参数定义了转换函数为 args 数组返回的内容。
【讨论】:
【参考方案3】:你可以使用MockPipe npm 包,但是你需要像下面这样导入它。
import MockPipe from 'mock-pipe';
之后,您需要做的就是在提供程序中定义您的模拟管道..
providers: [
provide: HighlightPipe,
useValue: MockPipe(HighlightPipe, () => 'mock')
]
就是这样。
【讨论】:
这在某一时刻可能是一个很好的解决方案,但该项目已经失效并且多年没有更新。它不适用于 Angular 11。【参考方案4】:将我的管道模拟成简单的类
export class DateFormatPipeMock
transform()
return '29.06.2018 15:12';
在我的规范文件中简单使用 useClass
providers: [
...
provide: DateFormatPipe, useClass: DateFormatPipeMock
...
]
为我工作:-)
【讨论】:
您也可以创建一个合法管道并将其添加到您的 TestBed 下,就像您应该做的那样。【参考方案5】:如果你想要可重用的 util 函数来模拟管道,你可以试试这个选项:
export function mockPipe(options: Pipe): Pipe
const metadata: Pipe =
name: options.name
;
return <any>Pipe(metadata)(class MockPipe );
然后在 TestBed 声明数组中调用这个函数:
TestBed.configureTestingModule(
declarations: [
SomeComponent,
mockPipe( name: 'myPipe' ),
mockPipe( name: 'myOtherPipe' )
],
// ...
).compileComponents();
【讨论】:
这对我有用,但是谁能详细解释这个返回语句? @Pommesloch 的 return 语句只是另一种写出 Dinistro 在另一个响应中所做的事情的方式。<any>Pipe()
位被修饰在随后的类声明中。对于它的价值,这里是对 shohrukh 的响应的轻微增强,允许返回模拟管道数据。它可能会帮助您形象化。 ``` 导出函数 mockPipe(options: Pipe, mockReturn: any): Pipe const metadata: Pipe = name: options.name ; return Pipe(metadata)( class MockPipe implements PipeTransform public transform = () => mockReturn; ); ```
我在 Angular 11 上,这似乎不起作用。他们可能在内部改变了一些东西。我收到错误“TypeError:无法读取未定义的属性‘调用’”
@MattM 使用 Zack 上面的一条评论中的代码。但是如果原来的答案也调整一下就好了。【参考方案6】:
您可以在TestBed
的declarations
中添加您的模拟管道:
TestBed.configureTestingModule(
declarations: [
AppComponent,
MockPipe
],
...
MockPipe
需要有带有原始名称的 @Pipe
装饰器。
import Pipe, PipeTransform from '@angular/core';
@Pipe(name: 'pipename')
class MockPipe implements PipeTransform
transform(value: number): number
//Do stuff here, if you want
return value;
【讨论】:
有没有办法使用 Jasmine 监视模拟管道?我正在尝试模拟翻译管道并检查它是否使用正确的翻译键调用。 模拟管道应该是您以该名称注册的唯一管道。我错误地导入了管道名称来源的模块。这阻止了我的 Mock 管道覆盖其原始实现。如果你在模拟管道,你的 Mock 应该是你注册的唯一实例,不要包括原始管道注册。 “不包括原始管道注册”eesh,如果 SUT 的导入超出您的控制范围,可能会很困难【参考方案7】:我们通常在模板中使用管道。这是模拟管道的方法。请注意,管道的名称必须与您正在模拟的管道相同。
@Pipe( name: 'myPipe' )
class MyPipeMock implements PipeTransform
transform(param)
console.log('mocking');
return true;
如果您在声明的组件模板中使用管道,则需要在配置您的 TestingModule 时包含管道。
【讨论】:
你如何用这个配置测试?【参考方案8】:要存根管道,请使用 Dinistro 的答案。要监视管道,您可以通过以下方式对其进行补充:
let pipeSpy: jasmine.Spy;
beforeEach(() =>
TestBed.configureTestingModule...
pipeSpy = spyOn(MockPipe.prototype, 'transform');
;
it('should do whatever', () =>
doYourStuff();
expect(pipeSpy).toHaveBeenCalled();
【讨论】:
另请注意:如果您不需要 MockPipe,可以在原始管道上spyOn
以上是关于测试组件时如何模拟管道的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jest 在 Nuxt 中测试组件时如何添加/模拟 Nuxt Auth 库
如何模拟在使用 Jest 测试的 React 组件中进行的 API 调用