我正在尝试测试一个使用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));
});
});
但在运行测试时,失败如下:
TypeError: Cannot read properties of undefined (reading 'ids')
141 | describe('layouts/TemplatesPanel', () => {
142 | beforeEach(() => {
> 143 | useSelector.mockImplementation(callback => callback(templates));
| ^
最好不要mockuseSelector
,mock实现可能会破坏它的函数,因为它的函数不仅仅是返回某个状态切片。请参阅useSelector
的实际实现,它不仅仅返回selectedState
。
推荐的方法是创建一个模拟存储并为其提供模拟数据
例如
index.tsx
:
import React from 'react';
import { useSelector } from 'react-redux';
export type Template = {
id: string;
name: string;
};
export type RootState = {
templates: Template[];
};
export const MyComp = () => {
const templates = useSelector<RootState>((state) => state.templates);
console.log('templates: ', templates);
return <div>MyComp</div>;
};
index.test.tsx
:
import { render } from '@testing-library/react';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { MyComp, RootState, Template } from '.';
describe('73494842', () => {
test('should pass', () => {
const templates: Template[] = [
{ id: '1', name: 'a' },
{ id: '2', name: 'b' },
];
const mockStore = createStore<RootState, any, any, any>((state = { templates }, action) => {
if (action.type === 'UPATE_NAME') {
return {
...state,
templates: templates.map((t) => (t.id === action.payload.id ? { ...t, name: action.payload.name } : t)),
};
}
return state;
});
render(
<Provider store={mockStore}>
<MyComp />
</Provider>
);
mockStore.dispatch({ type: 'UPATE_NAME', payload: { id: '1', name: 'c' } });
});
});
测试结果:
73494842
✓ should pass (44 ms)
console.log
templates: [ { id: '1', name: 'a' }, { id: '2', name: 'b' } ]
at MyComp (stackoverflow/73494842/index.tsx:14:11)
console.log
templates: [ { id: '1', name: 'c' }, { id: '2', name: 'b' } ]
at MyComp (stackoverflow/73494842/index.tsx:14:11)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.931 s, estimated 11 s
当我们稍后调度一个操作时,useSelector
钩子将订阅存储的更改,它将再次执行并获得更新的状态切片。如果您模拟它,只返回一个状态切片,则此功能将不再工作。