React测试:Jest+RTL测试点击Delete后模态框消失onDelete mock未调用问题
问题排查与解决方案
核心问题原因
- 你的
LinkForm组件内部定义的onDelete方法完全没有调用传入的props.onDelete,所以你测试时传入的mockDelete永远不会被触发 - 组件的删除按钮的
disabled状态由currentLink控制,你测试时直接使用了初始状态的store,大概率currentLink为空,按钮默认是禁用状态,点击操作不会触发任何回调 - 你当前的测试断言逻辑和需求完全相反:你要验证点击后
mockDelete调用1次、模态框消失,但现在写的是断言调用0次、组件可见 - 你要验证模态框消失,首先要明确模态框的显示隐藏逻辑:如果是父组件通过
currentLink是否存在来条件渲染LinkForm,单独渲染LinkForm的情况下是看不到消失效果的,因为你没有引入控制它显示/隐藏的上层逻辑
修复步骤
1. 修改组件代码
首先补充props定义,同时在内部删除逻辑执行完成后调用传入的onDelete回调:
// 补充props接口的onDelete定义 interface AFormProps { key: string; onSubmit: () => void; onCancel: () => void; onClick?: () => void; // 新增onDelete属性定义 onDelete?: () => void; classes: { button_basic: string; formControl: string; }; } const A: React.FC<AFormProps> = (props) => { // ...其他原有逻辑 const onDelete = () => { // Delete selected link from graph dispatch(removeLink(currentLink.id)); dispatch(changeLink("")); // 调用传入的onDelete回调 props.onDelete?.(); }; // ...其他原有逻辑 }
2. 修改测试代码
首先构造测试前置条件,保证删除按钮可用,再调整断言逻辑:
test("Testing if link is deleted when button 'Delete Link' is clicked", () => { const mockDelete = jest.fn(); // 提前给store写入测试用的currentLink数据,保证删除按钮不是禁用状态 store.dispatch(changeLink({ id: 'test-link-id' })); const props = { onDelete: mockDelete, }; render( <Provider store={store}> <LinkForm classes={{ button_basic: "", formControl: "" }} key="test-key" onSubmit={jest.fn()} onCancel={jest.fn()} {...props} /> </Provider> ); const deleteLinkButton = screen.getByRole("button", { name: /Delete Link/i, }); // 前置校验:按钮可见且可点击 expect(deleteLinkButton).toBeVisible(); expect(deleteLinkButton).not.toBeDisabled(); fireEvent.click(deleteLinkButton); // 校验删除回调被调用1次 expect(mockDelete).toHaveBeenCalledTimes(1); // 校验模态框消失:如果是条件渲染的模态框,用queryByTestId避免找不到直接报错 expect(screen.queryByTestId("LinkForm")).not.toBeInTheDocument(); });
额外注意事项
- 如果你的模态框显示隐藏是父组件控制的,单独测试
LinkForm时无法验证消失效果,建议将父组件也加入测试渲染逻辑,或者只验证onDelete被调用、redux action被正常触发即可,显示隐藏属于父组件的逻辑,不属于LinkForm本身的职责 - 建议测试时使用mock redux store,避免真实store的全局状态污染不同测试用例,每个测试用例执行前都重置状态
内容的提问来源于stack exchange,提问作者walee
相关产品推荐
相关产品推荐

