因?yàn)?code>enzyme沒有維護(hù)并且不支持react 18+,所以我正在嘗試將1750多個現(xiàn)有的單元測試遷移到react-testing-library
+ global-jsdom
來運(yùn)行,這樣我們的應(yīng)用程序就可以繼續(xù)運(yùn)行最新版本的react。我們所有的測試都是使用mocha
、chai
、enzyme
編寫的,我希望盡可能簡單地遷移。換句話說,我絕不會在一個全新的框架如jest
中重寫1750多個測試。
我正在嘗試按照使用react-testing-library
來對react組件進(jìn)行單元測試的示例。如果我在使用React.createElement
時使用簡單的元素,比如'div'
或'input'
,它就能正常工作,但是當(dāng)我使用material UI組件時,就會出現(xiàn)錯誤:
類型錯誤:無法讀取 null 的屬性(讀取“已注冊”) 在 C:\Users\user\Documents\project\node_modules@emotion\styled\base\dist\emotion-styled-base.cjs.dev.js:143:53
上述錯誤發(fā)生在<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了解更多關(guān)于錯誤邊界的信息。 堆棧跟蹤不準(zhǔn)確,但它在我嘗試執(zhí)行
h(Box, {},...)
(創(chuàng)建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組件渲染,但我似乎無法弄清楚是什么,或者這是否實(shí)際上是問題。關(guān)于這個特定錯誤的谷歌搜索結(jié)果不多。有什么想法嗎?
根據(jù)MUI庫的依賴關(guān)系,我發(fā)現(xiàn)它們在一些渲染過程中使用了@emotion/react和@emotion/styled,這似乎是MUI v5的一個問題,他們改變了緩存對象并意外地刪除了@emotion/react提供的緩存對象,這導(dǎo)致了TypeError: Cannot read property 'registered' of undefined
的錯誤,因?yàn)樗麄儧]有在新的緩存中添加cache.registered
。
解決方案:我通過在我的組件中包裝@emotion/react提供者({my component})來解決了這個問題。你可以嘗試按照@emotion.react提供的示例進(jìn)行操作:https://emotion.sh/docs/cache-provider
還要確保正確安裝了來自@emotion/react的依賴項(xiàng),可以運(yùn)行以下命令:npm install --save @emotion/react
或yarn add @emotion/react
代碼應(yīng)該如下所示:
這是使用更熟悉的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鏈?zhǔn)秸{(diào)用其他函數(shù)。