angular - 如何在 Angular 4 上使用 Typescript 2 和 Jasmine 2 模拟或监视没有对象的外部函数

标签 angular unit-testing typescript jasmine mocking

我想检查一个函数 haveBeenCalledWith() 是否有我需要的参数,这样我就可以检查我的调用是否正确,而不需要调用真正的方法。

我已经尝试了很多解决方案。我发现了一些 ( Using Jasmine to spy on a function without an object ) 和 ( How to spy a function without root object )

我的尝试可能有帮助 http://plnkr.co/edit/xmLCNffTvyD8rp9VcRex

我现在使用的外部库是 date-fns .

我在 Angular 4 中创建了一个管道,如下所示:

import { Pipe, PipeTransform } from '@angular/core';
// It works if I import all 'date-fns', but it gives me issues with three shaking, so that's not a proper solution
import * as format from 'date-fns/format'; 

@Pipe({
    name: 'dateFnsFormat'
})
export class DateFnsFormatPipe implements PipeTransform {

    transform(value: any, args?: any): any {
        return format(value, args);
    }

}

所以我想测试format函数的调用。

如果我在没有模拟的情况下进行测试。它有效:

import * as format from 'date-fns/format';

const xmasDay = '2017-12-25 12:30:00';

// Works with real function
it('should transform the date from Y-m-d H:m:s to d/m/Y', () => {
    const dateFnsFormatPipe = new DateFnsFormatPipe();
    expect(dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY')).toBe('25/12/2017');
});


// Works with real function
it('should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const dateFnsFormatPipe = new DateFnsFormatPipe();
    expect(dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss')).toBe('25/12/2017 12:30:00');
});

下面,我展示了我所有的尝试和以下错误:

// #1 Attempt with spyOn(window, 'function');
// @link https://stackoverflow.com/a/9511646/3415716
// Error: Error: format() method does not exist
it('#1 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    spyOn(window, 'format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(window.format).toHaveBeenCalled();
});

// #1b Attempt with spyOn(global, 'function');
// @link https://stackoverflow.com/a/9511646/3415716
// Error: Error: format() method does not exist
it('#1b should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    spyOn(global, 'format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(global.format).toHaveBeenCalled();
});

// #2 Attempt with jasmine.createSpy().and.callFake(function);
// @link https://stackoverflow.com/a/29922957/3415716
// Error: Expected spy unknown to have been called.
it('#2 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const test = jasmine.createSpy().and.callFake(format);

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(test).toHaveBeenCalled();
});


// #3 Attempt with jasmine.createSpy().and.callFake(function);
// @link https://stackoverflow.com/a/29922957/3415716
// Error: Expected spy testSpy to have been called.
it('#3 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const mySpy = jasmine.createSpy('testSpy', format).and.callThrough();

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(mySpy).toHaveBeenCalled();
});

// #4 Attempt with jasmine.createSpy(global, 'function');
// @link https://groups.google.com/forum/#!searchin/jasmine-js/spy$20function%7Csort:relevance/jasmine-js/a3gNCMMd3UM/6iP8jpfIAQAJ
//  Expected spy global to have been called.
it('#4 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const mySpy = jasmine.createSpy('global', format);
    const mySpyFormat = jasmine.createSpy('format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(mySpy).toHaveBeenCalled();
    expect(mySpyFormat).toHaveBeenCalled();
});

PS:我使用的示例在 date-fns 中,但是,我想用不同的库实现相同的想法。另外,我不想包含主文件,因为我希望从 webpack(阅读 https://github.com/ReactiveX/rxjs/issues/1888)中得到 three shaking

最佳答案

如果你尝试这样的事情......

it('should', () => {
      const dffp = new DateFnsFormatPipe();
      spyOn(DateFnsFormatPipe, 'transform').and.callThrough();
      spyOn(dffp, 'format');

      dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY');

      expect(dffp.format).toHaveBeenCalledWith(xmasDay, 'DD/MM/YYYY');
    })

我一直在用这个方法,效果很好。您可能需要稍微调整一下才能为您工作,但它应该很接近

关于angular - 如何在 Angular 4 上使用 Typescript 2 和 Jasmine 2 模拟或监视没有对象的外部函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44425113/

相关文章:

Angular:为什么我的 formArray 没有验证或更新?

c# - NUnit 中的静态或非静态测试夹具?

visual-studio-2010 - 在 Microsoft 单元测试中使用配置文件

c# - Unity IoC - 单元测试类型注册是否正确

javascript - formGroup 需要一个 FormGroup 实例。请在我在其他表单组中创建表单组时传入一个

angular - 我如何为 Angular 2 中的开发(而非测试)提供模拟服务?

带有 Tabulator 按钮的 Angular Material Tab 焦点

reactjs - 从路径显示 Markdown 文件与 typescript react

javascript - 在 React.memo 中需要 useCallback 吗?

angular - Bootstrap 4 使用 Angular 4 折叠导航栏