首頁  >  問答  >  主體

使用React Testing Library在jsdom中呈現MUI元件時,會引發Mocha測試錯誤

因為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粉946437474P粉946437474299 天前453

全部回覆(1)我來回復

  • P粉745412116

    P粉7454121162024-01-17 00:03:09

    根據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鍊式呼叫其他函數。

    回覆
    0
  • 取消回覆