use*_*141 14 reactjs jestjs redux enzyme react-redux
我有很多调用dispatch()(Redux)的功能性 React 组件。函数dispatch()本身是通过react-redux的hook传入的useDispatch()。
作为一个简化的例子:
const LogoutButton: FC = () => {
const dispatch: Dispatch = useDispatch();
return (
<button onClick={() => {
console.log("Clicked...") // To check that onClick() simulation is working
dispatch(authActions.logout())
}}>
LOGOUT
</button>
)
}
Run Code Online (Sandbox Code Playgroud)
使用 Jest 和 Enzyme,我需要做什么才能断言expect(dispatch).toHaveBeenCalledWith(authActions.logout)?
我没有模拟商店或使用 redux-mock-store 的功能。相反,我将组件包装在我为测试而制作的根组件中。它与我真正的 Root 组件相同,但需要设置测试的初始存储(和history.location)的道具:
const TestRoot: FC<RootProps> = ({ children, initialState = {}, initialEntries = defaultLocation }) => {
const store = createStore(reducers, initialState, applyMiddleware(thunk));
return (
<Provider store={store}>
<MemoryRouter initialEntries={initialEntries}>
<ScrollToTop />
<StylesProvider jss={jss}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</StylesProvider>
</MemoryRouter>
</Provider>
);
};
Run Code Online (Sandbox Code Playgroud)
它在测试中用于设置酶包装组件,例如:
wrappedLogoutButton = mount(
<TestRoot initialState={initialState}>
<LogoutButton />
</TestRoot>
);
Run Code Online (Sandbox Code Playgroud)
这个设置对我来说效果很好(到目前为止),如果不需要的话我不想改变它。我确实尝试将 redux-mock-store 模拟存储注入 TestRoot,但这搞乱了我编写的每个测试套件。
我尝试了多种模拟或监视两者的方法dispatch(),useDispatch()但我无法看到模拟被调用。模拟onClick()正在工作,因为我可以看到“Clicked...”被记录。这是一个示例测试(真实代码,不是简化示例):
test('should log learner out', () => {
const event = {
preventDefault: () => {},
target: { textContent: en.common['log-out-title'] } as unknown,
} as React.MouseEvent<HTMLButtonElement, MouseEvent>;
const wrappedLogOut = wrappedMenuDrawer.find(ListItem).at(3).find('a');
// @ts-ignore
act(() => wrappedLogOut.prop('onClick')(event));
// TODO: test authService.logout is called
// assert that dispatch was called with authActions.logout()
expect(amplitude.logAmpEvent).toHaveBeenCalledWith('from main menu', { to: 'LOGOUT' }); // This assertion passes
});
Run Code Online (Sandbox Code Playgroud)
根据文档、Medium 帖子和 Stack Overflow 上的类似问题,我尝试过在调度时进行模拟/间谍的方法/变体,包括:
import * as reactRedux from 'react-redux'
const spy = jest.spyOn(reactRedux, 'useDispatch'
Run Code Online (Sandbox Code Playgroud)
import store from '../../store';
const spy = jest.spyOn(store, 'dispatch')
Run Code Online (Sandbox Code Playgroud)
const mockUseDispatch = jest.fn();
const mockDispatch = jest.fn();
jest.mock('react-redux', () => ({
useDispatch: () => mockUseDispatch.mockReturnValue(mockDispatch),
}));
// or...
jest.mock('react-redux', () => ({
useDispatch: () => mockUseDispatch,
}));
mockUseDispatch.mockReturnValue(mockDispatch) // inside the actual test
Run Code Online (Sandbox Code Playgroud)
sid*_*cus 12
您可以通过多种方式执行此操作。AFAIK:
您可以模拟 useDispatch 钩子来返回您自己的假调度函数。我在我自己的 React 库的测试代码中使用了它来帮助管理到操作的绑定分派。这是hooks.test.tsx。
由于您使用测试 React 存储来包装组件,因此您还可以直接用伪函数替换 store.dispatch。请参阅此处进行讨论。
第一个的好处是,您可以根据需要轻松地从 React-Redux 模拟更多东西。
| 归档时间: |
|
| 查看次数: |
29871 次 |
| 最近记录: |