Jest 测试失败:TypeError: window.matchMedia 不是函数

IT技术 reactjs jestjs
2021-04-30 00:30:40

这是我第一次前端测试经验。在这个项目中,我使用 Jest 快照测试并且TypeError: window.matchMedia is not a function在我的组件中出现错误

我浏览了 Jest 文档,找到了“手动模拟”部分,但我还不知道如何做到这一点。

4个回答

Jest 文档现在有一个“官方”解决方法:

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(), // Deprecated
    removeListener: jest.fn(), // Deprecated
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
});

未在 JSDOM 中实现的模拟方法

我一直在使用这种技术来解决一堆模拟问题。

describe("Test", () => {
  beforeAll(() => {
    Object.defineProperty(window, "matchMedia", {
      writable: true,
      value: jest.fn().mockImplementation(query => ({
        matches: false,
        media: query,
        onchange: null,
        addListener: jest.fn(), // Deprecated
        removeListener: jest.fn(), // Deprecated
        addEventListener: jest.fn(),
        removeEventListener: jest.fn(),
        dispatchEvent: jest.fn(),
      }))
    });
  });
});

或者,如果您想一直模拟它,您可以将您的mocks文件放入从您的package.json: 调用文件中"setupFilesAfterEnv": "<rootDir>/src/tests/mocks.js",

参考:setupTestFrameworkScriptFile

在我的 Jest 测试文件中放置了一个matchMedia存根(在测试之上),它允许测试通过:

window.matchMedia = window.matchMedia || function() {
    return {
        matches: false,
        addListener: function() {},
        removeListener: function() {}
    };
};

Jest 使用jsdom来创建浏览器环境。但是 JSdom 不支持,window.matchMedia所以你必须自己创建它。

Jest 的手动模拟与module边界一起工作,即 require / import 语句,因此它们不适合按window.matchMedia原样模拟,因为它是全局的。

因此,您有两个选择:

  1. 定义您自己的本地 matchMedia module,该module导出 window.matchMedia。-- 这将允许您定义一个手动模拟以在您的测试中使用。

  2. 定义一个设置文件,将 matchMedia 的模拟添加到全局窗口。

使用这些选项中的任何一个,您都可以使用matchMedia polyfill作为模拟,它至少允许您的测试运行,或者如果您需要模拟不同的状态,您可能想要使用私有方法编写自己的方法,允许您配置它的行为类似于Jestfs手动模拟