如何在Jest中正确模拟音频API ?

  • 本文关键字:模拟 音频 API Jest jestjs
  • 更新时间 :
  • 英文 :


我正在编写一个测试,它需要模拟并提供访问工具来验证我的Audio实现是否正确。我成功地实现了我的设置方法,如下所示:

import "regenerator-runtime/runtime";
import { AudioState } from '../src';
export class MockAudio extends Audio {
src: string;
state: AudioState;
duration: number;
playing: boolean;
constructor() {
super();
this.playing = false;
this.duration = NaN;
this.state = AudioState.STOPPED;
this.src = '';
}
fastSeek = (time: number): Promise<void> => {
this.currentTime = time;
return Promise.resolve();
}
play = (): Promise<void> => {
this.playing = true;
this.state = AudioState.PLAYING;
return super.play();
}
pause = (): void => {
this.playing = false;
this.state = AudioState.PAUSED;
return super.pause();
}
}
HTMLMediaElement.prototype.pause = () => Promise.resolve();
HTMLMediaElement.prototype.play = () => Promise.resolve();
window.Audio = MockAudio;
Object.defineProperty(window, 'MediaSource', {
writable: true,
value: jest.fn().mockImplementation((params) => ({
// MediaSource implementation goes here
addEventListener: jest.fn(),
})),
});

正如你所看到的,我正在设置这些方法,以便它们能够以模拟音频API的方式影响对象属性。我想知道如何用mockImplementation和defineProperty正确地做到这一点?

您可以使用下面描述的方法解决此问题(或模仿任何其他内置API类):https://jestjs.io/docs/es6-class-mocks#manual-mock

我喜欢做的是首先定义我的mock,以便以后在test-utils.js中使用,像这样:

export const mocks = {
Audio: {
pause: jest.fn(),
play: jest.fn(),
},
}

现在我模拟我的jest.setup.js中的实际类(在jest配置中定义):

import { mocks } from "./test-utils"
// Audio mock
global.Audio = jest.fn().mockImplementation(() => ({
pause: mocks.Audio.pause,
play: mocks.Audio.play,
}))

,最后我可以期望在我的测试中的模拟:

import { mocks } from "./test-utils"
describe("Something", () => {
it("should work", () => {
// run your test here
expect(mocks.Audio.pause).toHaveBeenCalled()
})
})

当然记得在需要的时候清理模拟。

和我的package.json中jest配置的相关部分,以触发设置文件:

"jest": {
...,
"setupFilesAfterEnv": [
"<rootDir>/jest.setup.js"
],
...
},

似乎Audio.play()返回一个承诺:HTMLMediaElement.play(): Promise<void>

见:https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play

使用Typescript

时效果最好
global.Audio = jest.fn().mockImplementation(() => ({
pause: jest.fn(),
play: jest.fn(() => Promise.resolve()),
}));

你是正确的关于游戏返回承诺。但是,我仍然需要mock来查看方法是否被调用。疯狂的事情,这不能工作:

export const mocks = {
Audio: {
pause: jest.fn(),
play: jest.fn(() => Promise.resolve()),
},
}

代码中断说,在file.play().catch(...)返回:TypeError: Cannot read property 'catch' of undefined

不知何故返回的承诺丢失,play方法总是返回undefined。我尝试了所有可能的jest api,一切都给出了结果。但这工作play: () => Promise.resolve(),但我不能测试它是否被调用…

最新更新