使用Typescript

时间:2019-10-31 08:55:49

标签: typescript mocking jestjs

我正在用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);
});

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

在这种情况下是否可以通知TS查看模拟?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我有同样的问题,但只有解决方法。我的问题是我从节点手动模拟了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();

希望这对您有所帮助!