使用React Testing Library在jsdom中呈现MUI组件时,会引发Mocha测试错误
P粉946437474
P粉946437474 2024-01-16 13:49:47
0
1
496

因为enzyme没有维护并且不支持react 18+,所以我正在尝试将1750多个现有的单元测试迁移到react-testing-library + global-jsdom来运行,这样我们的应用程序就可以继续运行最新版本的react。我们所有的测试都是使用mochachaienzyme编写的,我希望尽可能简单地迁移。换句话说,我绝不会在一个全新的框架如jest中重写1750多个测试。

我正在尝试按照使用react-testing-library来对react组件进行单元测试的示例。如果我在使用React.createElement时使用简单的元素,比如'div''input',它就能正常工作,但是当我使用material UI组件时,就会出现错误:

类型错误:无法读取 null 的属性(读取“已注册”) 在 C:\Users\user\Documents\project\node_modules@emotion\styled\base\dist\emotion-styled-base.cjs.dev.js:143:53

上述错误发生在<Styled(div)>组件中:

at C:\Users\user\Documents\project\node_modules\@emotion\react\dist\emotion-element-b63ca7c6.cjs.dev.js:43:23
at Box (C:\Users\user\Documents\project\node_modules\@mui\system\createBox.js:29:41)
at DummyComponent (C:\Users\user\Documents\project\act-app\src\component\page\dummyComponent.js:2:346)

考虑为您的树添加错误边界以自定义错误处理行为。访问https://reactjs.org/link/error-boundaries了解更多关于错误边界的信息。 堆栈跟踪不准确,但它在我尝试执行h(Box, {},...)(创建mui元素)时失败。

这是我正在尝试渲染的dummyComponent.js

const { Box } = require('@mui/material');
const React = require('react');
const h = React.createElement;

const DummyComponent = (props) => {
  const { children } = props;
  const [showChild, setShowChild] = React.useState(false);
  return (
    h(Box, {},
      h('label', { htmlFor: 'toggle' }, 'Show/Hide'),
      h('input', { id: 'toggle', type: 'checkbox', onChange: (e) => setShowChild(e.target.checked), checked: showChild }),
      showChild && children)
  );
};

module.exports = DummyComponent;

这是mocha单元测试:

const React = require('react');
const { render, fireEvent } = require('@testing-library/react');
const h = React.createElement;

const DummyComponent = require('./dummyComponent');

describe('pageCenter', function () {
  before(function () {
    this.jsdom = require('global-jsdom')();
  });

  after(function () {
    this.jsdom();
  });

  it('should render', function () {
    const w = render(h(DummyComponent, {}, 'Hi!'));
    w.queryAllByText('Hi!').should.have.length(0);
    fireEvent.click(w.getByLabelText('Show/Hide'));
    w.queryAllByText('Hi!').should.have.length(1);
  });
});

感觉好像我缺少一些上下文来允许MUI组件渲染,但我似乎无法弄清楚是什么,或者这是否实际上是问题。关于这个特定错误的谷歌搜索结果不多。有什么想法吗?

P粉946437474
P粉946437474

全部回复(1)
P粉745412116

根据MUI库的依赖关系,我发现它们在一些渲染过程中使用了@emotion/react@emotion/styled,这似乎是MUI v5的一个问题,他们改变了缓存对象并意外地删除了@emotion/react提供的缓存对象,这导致了TypeError: Cannot read property 'registered' of undefined的错误,因为他们没有在新的缓存中添加cache.registered

解决方案:我通过在我的组件中包装@emotion/react提供者({my component})来解决了这个问题。你可以尝试按照@emotion.react提供的示例进行操作:https://emotion.sh/docs/cache-provider

还要确保正确安装了来自@emotion/react的依赖项,可以运行以下命令:npm install --save @emotion/reactyarn add @emotion/react

代码应该如下所示:

这是使用更熟悉的JSX语法的dummyComponent.js:

const React = require('react');
const { Box } = require('@mui/material');

const DummyComponent = (props) => {
  const { children } = props;
  const [showChild, setShowChild] = React.useState(false);

  return (
    <Box>
      <label htmlFor="toggle">Show/Hide</label>
      <input
        id="toggle"
        type="checkbox"
        onChange={(e) => setShowChild(e.target.checked)}
        checked={showChild}
      />
      {showChild && children}
    </Box>
  );
};

export default DummyComponent;

这是mocha单元测试:

const React = require('react');
const { expect } = require('chai');
const { render, fireEvent } = require('@testing-library/react');
const createCache = require("@emotion/cache");

const DummyComponent = require('./dummyComponent');

describe('pageCenter', function () {
  before(function () {
    this.jsdom = require('global-jsdom')();
  });

  after(function () {
    this.jsdom();
  });
  
  const myCache = createCache({
   key: 'my-prefix-key'
  });

  it('should render', function () {
    const { queryAllByText, getByLabelText } = render(
      <CacheProvider value={myCache}>          
        <DummyComponent>Hi!</DummyComponent>
      </CacheProvider>
    );

    expect(queryAllByText('Hi!')).should.have.length(0);
    fireEvent.click(getByLabelText('Show/Hide'));
    expect(queryAllByText('Hi!')).should.have.length(1);
  });
});

请注意,我在测试用例中还使用了一些JSX语法和const { expect } = require('chai');,这使我可以使用should和从chai链式调用其他函数。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板