如何测试类组件中点击按钮时的Redux Dispatch逻辑?
React Testing Library 测试按钮点击触发Redux动作失败排查
我尝试用React Testing Library测试按钮点击时的组件功能,但多次尝试都没成功。
组件代码
import React, { Component } from "react"; import { connect } from "react-redux"; class Table extends Component { render() { const { removeRegister } = this.props; return ( <button data-testid="delete-btn" onClick={() => removeRegister(0)}> Delete </button> ); } } const mapStateToProps = () => ({}); const mapDispatchToProps = (dispatch) => ({ removeExpense: (id) => dispatch({ type: "REMOVE_REGISTER", payload: { id }, }), }); export default connect(mapStateToProps, mapDispatchToProps)(Table);
测试代码
it("should trigger the actions when clicking on the buttons", () => { renderWithRouterAndRedux(<Table />, { state: mockState, }); const deleteBtn = screen.getAllByTestId("delete-btn")[0]; userEvent.click(deleteBtn); expect(store.dispatch).toHaveBeenCalledWith({ type: "REMOVE_REGISTER" }); });
问题排查与修复
1. Props名称不匹配
组件中调用的removeRegister并未在mapDispatchToProps中定义,实际导出的props是removeExpense,这会导致点击按钮时调用未定义方法,根本不会触发Redux dispatch。
修复方式二选一:
- 组件内改用正确的props名称:
// 组件render方法内 const { removeExpense } = this.props; // 按钮onClick改为 onClick={() => removeExpense(0)}
- 或修改
mapDispatchToProps的key为removeRegister:
const mapDispatchToProps = (dispatch) => ({ removeRegister: (id) => dispatch({ type: "REMOVE_REGISTER", payload: { id }, }), });
2. 断言内容不完整
测试中只断言了action的type,但组件实际触发的action包含payload: {id:0},需要完整匹配action对象才能通过断言。
修正后的断言:
expect(store.dispatch).toHaveBeenCalledWith({ type: "REMOVE_REGISTER", payload: { id: 0 } });
3. 确保Store的Dispatch被正确监听
需要确保测试中能获取到Redux store,并且对dispatch方法进行spy监听。如果renderWithRouterAndRedux返回的对象包含store实例,直接使用即可;如果没有,需要手动添加spy:
修正后的测试代码:
it("should trigger the actions when clicking on the buttons", () => { // 获取render返回的store const { store } = renderWithRouterAndRedux(<Table />, { state: mockState, }); // 对dispatch方法进行spy jest.spyOn(store, 'dispatch'); // 单个按钮用getByTestId即可,无需getAll const deleteBtn = screen.getByTestId("delete-btn"); userEvent.click(deleteBtn); expect(store.dispatch).toHaveBeenCalledWith({ type: "REMOVE_REGISTER", payload: { id: 0 } }); });
内容的提问来源于stack exchange,提问作者LayTexas
相关产品推荐
相关产品推荐

