使用 Jest、AudioContext 进行测试和模拟

Posted

技术标签:

【中文标题】使用 Jest、AudioContext 进行测试和模拟【英文标题】:Testing and Mocking with Jest, AudioContext 【发布时间】:2019-09-01 02:56:55 【问题描述】:

我在尝试对使用 AudioContext 的类进行一些测试时遇到了很多麻烦。我相信我的很多挫败感源于对模拟函数以及可能如何执行测试没有很好的理解。

我正在尝试测试一个使用 AudioContext 的类,但是当我运行测试时我不断收到此错误:

使用 TypeScript 文件时: TypeError: (window.AudioContext || window.webkitAudioContext) 不是构造函数 此错误发生在 app.ts 文件中。当我运行测试时,它是否必须解析或执行它的所有依赖项?

使用 javascript 文件时,测试文件中会出现此错误:ReferenceError: AudioContext is not defined

现在,我假设我必须制作一个模拟 AudioContext。我什至如何了解 AudioContext 上的所有方法才能开始手动模拟它?

这是我的工作表的简化版本。我将提供两者的 TS 和 JS 版本:

TypeScript 文件版本:

// app.ts
import Sampler from './Sampler';
const audioContext: AudioContext = new (window.AudioContext || window.webkitAudioContext)();
const sampler: Sampler = new Sampler(audioContext);


// Sampler.ts
export default class Sampler
    private audioContext: AudioContext;

    constructor(audioContext: AudioContext)
        this.audioContext = audioContext;      
    
 

JS 文件版本:

// app.js
const Sampler = require('./Sampler');
const audioContext =  new (window.AudioContext || window.webkitAudioContext)();
const sampler = new Sampler(audioContext);

// Sampler.js
class Sampler
    constructor(audioContext)
        this.audioContext = audioContext;   
    

module.exports = Sampler;

测试文件以粗体显示我之前提到的错误:

// sampler.test.ts

import Sampler from './Sampler';
// Uncomment line below if you're using plain JS and not TS
// const Sampler = require('./Sampler');

test('Test test', () => 
  const audioContext = new AudioContext();
  const s = new Sampler(audioContext);
)

更新: 我现在有适用于纯 JS 文件的代码。我在测试中添加了一个空的 AudioContext 模拟。

// sampler.test.js
const Sampler = require('./Sampler');
require('./__mocks__/app');


test('Testing Mock AudioContext', () => 
    const audioContext = new AudioContext();
    const s = new Sampler(audioContext);
)


// __mocks__/app.js
window.AudioContext = jest.fn().mockImplementation(() => 
    return 
);

由于我的项目是用 TypeScript 编写的,所以我尝试将模拟添加到我的项目中,但我仍然收到上面的错误“TypeError: (window.AudioContext || window.webkitAudioContext) is not a constructor”。

谢谢:)。

【问题讨论】:

【参考方案1】:

旧帖子,但我想我会分享我如何处理打字稿错误。为了保持 Typescript 和类型的优势,我只是将 webkitAudioContext 添加到定义的 Window 类型中。我的代码如下:

declare var window: 
  webkitAudioContext: typeof AudioContext;
 & Window & typeof globalThis;

const audioContext = new (window.AudioContext || window.webkitAudioContext)();

这实际上是告诉 typescript 将 Window & typeof globalThis 与新的 webkitAudioContext 属性联合起来。

ReferenceError: AudioContext is not defined 错误而言,这很可能是因为 AudioContext 没有被嘲笑(就像你说的那样——这也是我偶然发现的问题在你的帖子上)。我知道 jest 使用 jsdom 来模拟 dom。 jsdom currently doesn't support AudioContext mocks

【讨论】:

【参考方案2】:

您可以通过将窗口指定为“any”类型来解决此问题,即

const audioContext: AudioContext = 
 new (AudioContext || (window as any).webkitAudioContext)();

正如here所描述的那样。

请注意,我认为您不需要通过代码中的窗口访问 AudioContext,因为这应该可用。

【讨论】:

不幸的是,这不起作用。我确实认为我可以利用它来解决编译器错误。我创建了一个 window.d.ts 文件夹并将我的 AudioContext 放在那里以解决编译器错误,但我理解您提出的更多建议。奇怪的是,我在我的项目的一个简单的 TypeScript 版本上进行了测试和模拟,但在我的实际项目中我仍然从上面得到 TypeError。 我想一种解决方法可能是制作一个 AudioContextMock 类并执行 - const audioContext: AudioContext = new (AudioContext || (window as any).webkitAudioContext || AudioContextMock)();这样我就不会在 Node 中得到错误。 道歉 - 我在第一条评论中犯了一个错误。使用您发布的代码 sn-p,我在运行测试时收到“参考错误:未定义 AudioContext”,而不是 TypeError。 在那种情况下,您是否尝试使用 (window as any).AudioContext?

以上是关于使用 Jest、AudioContext 进行测试和模拟的主要内容,如果未能解决你的问题,请参考以下文章

使用Jest进行单元测试

使用 Jest 和 Webpack 别名进行测试

使用 Node 进行 Jest 测试 - 超时 - 在 jest.setTimeout 指定的 5000 毫秒超时内未调用异步回调

使用 Jest 进行测试的共享 utils 函数

使用 React、Typescript 和 ES6 进行 Jest 测试

如何使用 Jest 对 quasar 应用程序进行单元测试?