我正在用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查看模拟?
答案 0 :(得分:2)
解决此问题的最简单方法是使用ts-jest的mocked()
帮助程序。助手将确保您有权访问模拟测试方法。 __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();
希望这对您有所帮助!