Mar*_*tes 3 unit-testing reactjs jestjs react-redux react-testing-library
我正在尝试测试一个使用react-redux 进行状态管理的组件。
为了快速测试,我想模拟 useSelector,如下所示:
const templates = [
{
id: ...,
name: ...,
...
},
{
id: ...,
name: ...,
...
},
]
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: jest.fn(),
}));
describe('some awesome description', () => {
beforeEach(() => {
useSelector.mockImplementation(callback => callback(templates));
});
});
Run Code Online (Sandbox Code Playgroud)
但在运行测试时,会失败,如下所示:
TypeError: Cannot read properties of undefined (reading 'ids')
141 | describe('layouts/TemplatesPanel', () => {
142 | beforeEach(() => {
> 143 | useSelector.mockImplementation(callback => callback(templates));
| ^
Run Code Online (Sandbox Code Playgroud)
最好不要使用mock useSelector,mock的实现可能会破坏它的功能,因为它的功能不仅仅是返回某个状态片。查看useSelector 真正的实现,它不只是返回selectedState.
推荐的方法是创建一个模拟商店并为其提供模拟数据。
\n例如
\nindex.tsx:
import React from \'react\';\nimport { useSelector } from \'react-redux\';\n\nexport type Template = {\n id: string;\n name: string;\n};\nexport type RootState = {\n templates: Template[];\n};\n\nexport const MyComp = () => {\n const templates = useSelector<RootState>((state) => state.templates);\n console.log(\'templates: \', templates);\n return <div>MyComp</div>;\n};\nRun Code Online (Sandbox Code Playgroud)\nindex.test.tsx:
import { render } from \'@testing-library/react\';\nimport React from \'react\';\nimport { Provider } from \'react-redux\';\nimport { createStore } from \'redux\';\nimport { MyComp, RootState, Template } from \'.\';\n\ndescribe(\'73494842\', () => {\n test(\'should pass\', () => {\n const templates: Template[] = [\n { id: \'1\', name: \'a\' },\n { id: \'2\', name: \'b\' },\n ];\n const mockStore = createStore<RootState, any, any, any>((state = { templates }, action) => {\n if (action.type === \'UPATE_NAME\') {\n return {\n ...state,\n templates: templates.map((t) => (t.id === action.payload.id ? { ...t, name: action.payload.name } : t)),\n };\n }\n return state;\n });\n render(\n <Provider store={mockStore}>\n <MyComp />\n </Provider>\n );\n mockStore.dispatch({ type: \'UPATE_NAME\', payload: { id: \'1\', name: \'c\' } });\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n测试结果:
\nimport React from \'react\';\nimport { useSelector } from \'react-redux\';\n\nexport type Template = {\n id: string;\n name: string;\n};\nexport type RootState = {\n templates: Template[];\n};\n\nexport const MyComp = () => {\n const templates = useSelector<RootState>((state) => state.templates);\n console.log(\'templates: \', templates);\n return <div>MyComp</div>;\n};\nRun Code Online (Sandbox Code Playgroud)\n当我们稍后发送一个动作时,useSelector钩子将订阅存储的更改,它将再次执行并获取更新的状态切片。如果你模拟它只是返回一个状态切片,那么这个功能就不再起作用了。
| 归档时间: |
|
| 查看次数: |
17498 次 |
| 最近记录: |