我有一个使用 react-redux 的反应应用程序,使用 selector 从存储中获取数据。 反应组件具有
function PersonDataView() {
const name= useSelector(state => state.data.name)
const dob= useSelector(state => state.data.dob)
const dispatch = useDispatch()
const show= () => dispatch({type: 'SHOW'})
const remove= () => dispatch({type: 'REMOVE'})
return (
<div>
<h2>Person Details</h2>
<div>
<button onClick={show}>Show</button>
<span aria-label="name">{name}</span>
<span aria-label="dob">{dob}</span>
<button onClick={remove}>Remove</button>
</div>
</div>
)
}
我正在使用反应测试库来测试这个组件。是否有任何 API 可以让我们更轻松地测试这些组件。我知道测试这些的两种方法: 1(我可以使用redux-mock-store模拟商店,然后将此组件包装在提供者组件下。 2(开玩笑地模拟使用选择器方法
jest.mock('react-redux', () => ({
useSelector: () => ({
})
});
但是使用jest mock的问题是在多个选择器的情况下,所有useSelectors将返回相同的模拟值。 使用嘲笑方式,jest.fn((.mockReturnValueOnce(( 对我来说看起来不正确。
我建议不同的方法 - 将选择器提取到单独的文件中,例如文件选择器.js:
const nameSelector = state => state.data.name;
const dobSelector = state => state.data.dob;
然后在测试中,你可以模拟useSelector,如下所示:
jest.mock('react-redux', () => ({
useSelector: jest.fn().mockImplementation(selector => selector()),
}));
并分别模拟选择器,例如:
jest.mock('./selectors.js', () => ({
nameSelector: jest.fn().mockReturnValue("myTestName"),
dobSelector: jest.fn().mockReturnValue("myTestDob"),
}));
试试这个:
jest.mock('react-router');
const useSelectorMock = useSelector as any;
describe('something', () {
test('name', () => {
// Use this for each useSelector call:
useSelectorMock.mockImplementationOnce(jest.fn(() => returnValue as yourType));
}
}
试试这种方法:
jest.mock('react-redux', () => ({
useSelector: jest.fn().mockImplementation(func => func(store))
});
您还应该在此处添加一个图层:
jest.mock('react-redux', () => {
const store = {
data: {
name: {
...
},
dob: {
...
}
}
};
嘲笑 Redux 不是一个好习惯。你想测试 Redux 和 React 组件之间的集成,而不是选择器的 Redux 实现。如果您使用react-testing-library
则劫持render()
方法并使用Redux提供程序组件实现商店非常简单。下面是设置可重用测试渲染函数的文档和建议方法。
下面是一个使用 React 测试库 + Jest 的示例测试:
import { renderWithProviders } from '../../test-utils' // <-- Hijacked render
it('displays data when ready', {
renderWithProviders(<YourComponent />, {
initialState: {
dataready: true // <-- Pass data for selector
}
})
expect(screen.getByText('data reader')).toBeInTheDocument();
})