玩笑间谍On navigator.mediaDevices

Udd*_*ers 1 javascript dom spy typescript jestjs

我目前正在编写一个小型库来帮助连接到媒体设备,如果我可以对该库进行单元测试,那就太好了,我的打字稿库中有一个如下所示的函数,

static connectAudioDevice(device?: InputDeviceInfo) : Promise<MediaStream> {
    return new Promise<MediaStream>((resolve, reject) => {
        navigator.mediaDevices.getUserMedia({audio: true})
            .then(stream => {
                resolve(stream);
            })
            .catch(error => {
                resolve(error);
            })
    })
}
Run Code Online (Sandbox Code Playgroud)

我想用它jest.spyOn来模拟getUserMedia这可能吗?就像是,

import devices from '@/assets/lib/devices.ts';

test('Resolves with valid audio mediaStream', () => {

    const audioStream = {};
    let promise = devices.connectAudioDevice();

    jest.spyOn(window.navigator.mediaDevices, 'getUserMedia', promise);

})
Run Code Online (Sandbox Code Playgroud)

但我收到错误:

无法监视原始值;未定义给定

有人能给我一些帮助吗?

sli*_*wp2 6

navigator.mediaDevices不是由 JSDOM 实现的。window.navigator.mediaDevices也是如此undefined,这就是您收到错误的原因。看一下JSDOM 中未实现的 Mocking 方法

\n

解决办法是:

\n

device.ts:

\n
export default class Devices {\n  public static connectAudioDevice(device?: InputDeviceInfo): Promise<MediaStream> {\n    return new Promise<MediaStream>((resolve, reject) => {\n      navigator.mediaDevices\n        .getUserMedia({ audio: true })\n        .then((stream) => {\n          resolve(stream);\n        })\n        .catch((error) => {\n          resolve(error);\n        });\n    });\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

device.test.ts:

\n
import devices from \'./deivce\';\n\ndescribe(\'65112057\', () => {\n  test(\'Resolves with valid audio mediaStream\', async () => {\n    const mockMediaDevices = {\n      getUserMedia: jest.fn().mockResolvedValueOnce(\'fake data\' as any),\n    };\n    Object.defineProperty(window.navigator, \'mediaDevices\', {\n      writable: true,\n      value: mockMediaDevices,\n    });\n    const actual = await devices.connectAudioDevice();\n    expect(actual).toBe(\'fake data\');\n    expect(mockMediaDevices.getUserMedia).toBeCalledWith({ audio: true });\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

单元测试结果:

\n
\n PASS  src/stackoverflow/65112057/device.test.ts\n  65112057\n    \xe2\x9c\x93 Resolves with valid audio mediaStream (7ms)\n\n-----------|----------|----------|----------|----------|-------------------|\nFile       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |\n-----------|----------|----------|----------|----------|-------------------|\nAll files  |       80 |      100 |       75 |       80 |                   |\n deivce.ts |       80 |      100 |       75 |       80 |                10 |\n-----------|----------|----------|----------|----------|-------------------|\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        4.994s, estimated 13s\n
Run Code Online (Sandbox Code Playgroud)\n