测试组件时如何模拟管道

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 在另一个响应中所做的事情的方式。 &lt;any&gt;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】:

您可以在TestBeddeclarations 中添加您的模拟管道:

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 调用

使用 Vuex 时如何测试 Vuejs 组件

Angular - 测试组件 - 从模拟返回 Promise.reject 时出错

使用模拟服务时在业力测试中调用 OnInit() 后组件未定义