【问题标题】:Import function from a Jest manual mock with Typescript使用 Typescript 从 Jest 手动模拟中导入函数
【发布时间】:2020-02-26 14:24:27
【问题描述】:

我正在 Typescript 项目中使用 Jest 创建一个自定义模拟(ES6 类)。模拟创建了几个mock.fn() 的最终导出,以便可以在测试套件中监视它们。

一个例子可以是来自 Jest 文档 (https://jestjs.io/docs/en/es6-class-mocks#manual-mock) 的官方例子。在那里,SoundPlayer 类已被模拟,因为它是它唯一的方法playSoundFile。该方法使用jest.fn() 模拟,导出以用于测试。

// soundPlayer.ts
export default class SoundPlayer {
  foo: string = 'bar';

  playSoundFile(filename: string) {
    console.log(`Playing sound file ${filename}`);
  }
}
// __mocks__/soundPlayer.ts
export const mockPlaySoundFile = jest.fn();

const mock = jest.fn().mockImplementation(() => {
  return { playSoundFile: mockPlaySoundFile };
});

export default mock;
// __tests__/soundPlayer.ts
import SoundPlayer, { mockPlaySoundFile } from '../soundPlayer';

jest.mock('../soundPlayer');

beforeEach(() => {
  mockPlaySoundFile.mockClear();
});

it('is called with filename', () => {
  const filename = 'song.mp3';
  const soundPlayer = new SoundPlayer();
  soundPlayer.playSoundFile(filename);

  expect(mockPlaySoundFile).toBeCalledWith(filename);
});

测试按预期工作,但 TS 在尝试导入模拟的 mockPlaySoundFile 函数时通知错误(这对我来说很有意义)。那是因为mockPlaySoundFile 显然不存在于soundPlayer.ts 中。但是由于 jest.mock('../soundPlayer'); 模拟是在后台导入的,因此导出确实存在。

有没有办法通知 TS 在这种情况下查看模拟?

【问题讨论】:

标签: typescript mocking jestjs


【解决方案1】:

我有同样的问题,我只有一个解决方法。我的问题是我从节点手动模拟 fs。

所以我有一个“fs”的手动模拟,大致如下:

const fs = jest.genMockFromModule("fs");

let mockFiles = {};

function __clearMocks(){
    mockFiles = {};
}

module.exports = fs;

很明显,当我的测试用例导入 fs 时它不起作用:

import * as fs from 'fs';
fs.__clearMocks();

为了让它工作,我创建了一个类型的扩展:

declare module 'fs' {
    export function __clearMocks(): void; 
}

所以现在我可以像这样修改我的测试用例:

import * as fs from 'fs';
import 'fsExtension';
fs.__clearMocks();

希望对您有所帮助!

【讨论】:

    【解决方案2】:

    解决此问题的最简单方法是使用ts-jestmocked() 助手。助手将确保您可以访问模拟测试方法。 __tests__/soundPlayer.ts 将如下所示:

    // __tests__/soundPlayer.ts
    import { mocked } from "ts-jest/utils";
    import SoundPlayer from '../soundPlayer';
    
    jest.mock('../soundPlayer');
    
    const soundPlayer = mocked(new SoundPlayer());
    
    beforeEach(() => {
      soundPlayer.playSoundFile.mockClear();
    });
    
    it('is called with filename', () => {
      const filename = 'song.mp3';
    
      soundPlayer.playSoundFile(filename);
    
      expect(soundPlayer.playSoundFile).toBeCalledWith(filename);
    });
    

    如果你真的想包含mockPlaySoundFile,你可以通过告诉 Typescript 编译器抑制导入错误来做到这一点:

    // @ts-ignore
    import { mockPlaySoundFile } from '../soundPlayer';
    

    另外,请查看我的仓库中的示例:https://github.com/tbinna/ts-jest-mock-examples,尤其是您的 soundPlayer 示例:https://github.com/tbinna/ts-jest-mock-examples/tree/master/sound-player

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 2019-05-17
      • 2019-12-08
      • 2019-07-08
      • 2022-07-22
      • 1970-01-01
      • 2019-08-11
      相关资源
      最近更新 更多