How to write unit test for Material UI slider? "Error: Cannot read property 'addEventListener' of null" thrown when attempting to render component

How to write unit test for Material UI slider? "Error: Cannot read property 'addEventListener' of null" thrown when attempting to render component

尝试使用 Reat-Test-Renderer 测试 Material-UI 滑块时出现错误:Uncaught [TypeError: Cannot read property 'addEventListener' of null]

Codesandbox Link

import React from "react";
import { Slider } from "@material-ui/core";
import renderer from "react-test-renderer";

it("should render", () => {
  renderer.create(<Slider />);
});

我所知道的任何其他 Material UI 组件都不是这种情况。

它似乎与描述的 forwardRef 有关 here,但我想不出一个方法让它工作。

编辑 不幸的是,切换到 @testing-library/react 不是我正在处理的这个项目的选项。

编辑 2 我这样做的原因是因为我试图渲染和测试我自己的一个更复杂的组件,其中包含滑块。我花了一段时间才弄清楚这就是导致问题的原因,上面的代码是复制问题的最少代码量。

编辑 3 错误消息截图

React Test Renderer 仅将组件渲染为 JS 对象,而不是浏览器环境。因此,任何使用基于 dom 的引用都会有这个问题。相关笑话问题:https://github.com/facebook/jest/issues/5462.

React 文档中有一个部分提供解决方法:https://reactjs.org/docs/test-renderer.html#ideas

编辑:

这是一个工作测试。这可能会使滑块的许多功能无法正常工作,因为我们将内部引用设置为 null。但确实 运行。 MUI 上的“Next”b运行ch 没有 findDOMNode 函数,因此可能更容易使用。

我无法让它们在 CodeSandbox 上运行,因为 jest 未定义,而且我找不到解决方法。

import React from 'react';
import { Slider } from '@material-ui/core';
import renderer from 'react-test-renderer';

jest.mock('react-dom', () => ({
  // the useIsFocusVisible function in Slider.js (MUI component) uses findDOMNOde
  // Luckily it checks if there's nulls, so we can return a null
  // https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/useIsFocusVisible.js#L136
  findDOMNode: () => null,
}));
it('should render', () => {
  renderer.create(<Slider />);
});

如果您想尝试模拟全部功能(某种程度上),您可以使用 findDOMNode 模拟的这个实现,它将 return useIsFocusVisible 所需的值运行 成功包括添加事件侦听器:

import React from 'react';
import { Slider } from '@material-ui/core';
import renderer from 'react-test-renderer';

jest.mock('react-dom', () => ({
  // the useIsFocusVisible function in Slider.js (MUI component) uses findDOMNOde
  // https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/useIsFocusVisible.js#L136
  findDOMNode: (instance) => {
    return { ownerDocument: instance };
  },
}));
it('should render', () => {
  let eventListenerFn = jest.fn();
  renderer.create(<Slider />, {
    createNodeMock: (element) => {
      if (element.type === 'span') {
        return {
          addEventListener: eventListenerFn,
        };
      }
    },
  });
});

为了弄清楚如何让这些测试成功 运行,我不得不逐步检查错误 stacks/MUI 源代码以找出问题所在以及需要的值为了不抛出错误而被嘲笑。


原创,展示了@testing-library在这方面的优势:

但是,我可以建议使用 @testing-library 吗?很高兴使用 jsdom 来呈现组件,因此它可以与此组件一起使用。

我继续使用测试库对 Slider 进行了几次 运行dom 测试,以表明它可以与 Slider 一起使用并且没有抛出任何错误:

import React from "react";
import { Slider } from "@material-ui/core";
import { render } from "@testing-library/react";

it("should render", () => {
  render(<Slider />);
});

it("should render an input", () => {
  const component = render(<Slider />);
  const input = component.baseElement.querySelector("input");
  expect(input).toBeDefined();
});

it("Should have the correct value", () => {
  const component = render(<Slider value={50} />);
  const input = component.baseElement.querySelector("input");
  expect(input.value).toBe("50");
});

CodeSandbox