【问题标题】:How to mock navigator mediaDevices for Jest如何为 Jest 模拟导航器 mediaDevices
【发布时间】:2021-03-20 19:25:08
【问题描述】:

我有一个需要使用 navigator.mediaDevices 的测试,但我无法让任何模拟正常工作。

我正在使用create-react-app

这是我的测试:

import getConnectedDevices from "./getConnectedDevices";

describe("getConnectedDevices", () => {
  it("Should work", () => {
    console.log(navigator);              // Navigator {}
    console.log(navigator.mediaDevices); // undefined
  });
});

我尝试添加一个模拟,因为它声明 here in the jest documentation

// tests/navigator.mock
Object.defineProperty(window, "navigator", {
  writable: true,
  value: {
    mediaDevices: {
      enumerateDevices: jest.fn(),
    },
  },
});

import "../../tests/navigator.mock"; // <- Mock added

import getConnectedDevices from "./getConnectedDevices";

describe("getConnectedDevices", () => {
  it("Should work", () => {
    console.log(navigator);              // Navigator {}
    console.log(navigator.mediaDevices); // undefined
  });
});

根据 create-react-app 文档,我也尝试过 Initializing the test environment

// src/setupTests.ts

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";

const navigatorMock = {
  mediaDevices: {
    enumerateDevices: jest.fn(),
  },
};

global.navigator = navigatorMock;

我做错了什么?

【问题讨论】:

    标签: reactjs unit-testing jestjs navigator


    【解决方案1】:

    我是用打字稿做的:

    const mockGetUserMedia = jest.fn(async () => {
        return new Promise<void>(resolve => {
            resolve()
        })
    })
    
    Object.defineProperty(global.navigator, 'mediaDevices', {
        value: {
            getUserMedia: mockGetUserMedia,
        },
    })
    

    【讨论】:

    • 谢谢!这应该是公认的答案。
    • 请注意,使用 ES6,您可以删除 return 语句和大括号以简化您的功能: const mockGetUserMedia = jest.fn( async () => new Promise(resolve => { resolve (); }) );
    • 我认为这个答案需要更多澄清信息。与测试相比,这到底是在哪里调用的,在 jest 之外是否需要任何库?我也尝试实现此代码,但它不会为我将“mediaDevices”添加到导航器属性中。
    • 您可以简化为const mockGetUserMedia = jest.fn(async () =&gt; {});jest.fn(Promise.resolve);
    【解决方案2】:

    似乎因为已经有一个navigator 对象,所以无法重新分配它。

    感谢this stackoverflow answer,您模拟了navigator 中的对象并将其分配给现有的导航器对象。

    // src/setupTests.ts
    
    const mediaDevicesMock = {
      enumerateDevices: jest.fn(),
    };
    
    global.navigator.mediaDevices = mediaDevicesMock; // here
    

    注意:这将引发 TSC 错误Cannot assign to 'mediaDevices' because it is a read-only property.ts(2540)。仍在努力解决这个问题。

    【讨论】:

    • 您可以使用Object.defineProperty(),如果您稍后在某些测试中要覆盖它,请不要忘记添加{ writable: true }
    猜你喜欢
    • 2019-05-17
    • 2021-01-21
    • 2019-02-15
    • 1970-01-01
    • 2019-06-10
    • 2018-06-30
    • 2019-04-16
    相关资源
    最近更新 更多