如何更便利的使用 React Testing Library、需要注意的配置細節
2023-11-180.51Front EndReactTesting
一個簡單的測試
定位方法參考使用結果

我們可以使用render測試指定組件,如下:
test('render componet', () => { render(<MyComponent />); });
測試組件需要注意的事
Provider
但如果有使用 redux 或 react-router-dom… 等套件或context provider,直接使用組件是不行的,因為組件並沒有被包裹在Provider中,測試時會報錯

我們需要手動加上provider :
import { Provider } from 'react-redux' import { BrowserRouter as Router } from 'react-router-dom' import { store } from '@/store' test('test target', () => { render( <Provider store={store}> <Router> <MyComponent /> </<Router> </Provider > ); });
如果要測試指定路由怎麼辦呢?
我們可以使用 window.history.pushState
直接移動到指定路由下 :
test('test target', () => { window.history.pushState({}, 'Test Page', '/new-route') render(<MyComponent />); });
封裝再測試
如果每次測試都傳一大堆provider,或是指定測試路徑時都要寫一次 window.history.pushState
,豈不是累死自己,我們可以封裝 render
加入如 : provider、route、localStorage... 等 enhance 多項功能
新增一個檔案 test-utils
用來存放封裝產物,爾後使用react-testing-library相關功能時直接導入這個文件即可,美哉。
// test-utils import { render as rtlRender } from '@testing-library/react' import React, { ReactNode } from 'react' import AppProvider from '@/provider' function render( ui: React.ReactElement, { route = '/', ...renderOptions } = {} ) { localStorage.setItem('jwt', 'token') window.history.pushState({}, 'Test Page', route) function Wrapper({ children }: { children: ReactNode }) { return <AppProvider>{children}</AppProvider> } return rtlRender(ui, { wrapper: Wrapper, ...renderOptions }) } export * from '@testing-library/react' export { render }
每個 test
中可能會執行一些操作,如添加事件監聽器、修改全局狀態等,為確保每次測試的獨立性,可以在測試文件使用 afterEach
清除相關殘留。
import server from '@/mock/server' import { cleanup } from './test-utils' afterEach(() => { server.resetHandlers() // 這是msw的mock api server cleanup() // 清除render組件狀態、副作用 })
錯誤排除
測試時搭配 axios 呼叫 api 會報錯 ({"Object.":function(module,exports,require,__dirname,__filename,jest){import axios from './lib/axios.js';

需要在 package.json 中 scripts 的test指令後面加上 --transformIgnorePatterns "node_modules/(?!axios)/
react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\