You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Jest中监听React useReducer时Mock dispatch函数未触发问题排查

React useReducer 测试:Mock dispatch 未被调用的问题

我有一个采用useReducer模式的React应用,需要测试dispatch函数的输入值——直接断言组件内部状态既不简便也无意义,因此计划通过Mock React.useReducer,让它返回一个可用于断言的Mock dispatch函数。但目前遇到的问题是:Mock的dispatch函数从未被调用。

待测试组件代码

interface IState {
    name: string
}

interface IAction {
    type: "fetched data" | "manual update"
    newName: string
}

interface ITestComponentProps {
    name: string
}

const TestReducerComponent: React.FC<ITestComponentProps> = (props) => {
    const { name } = props;
    const initState = { name: name };

    const handleUpdates = (state: IState, action: IAction): IState => {
        console.log("handle updates was called with " + action.newName);
        return { name: action.newName };
    }

    // 原代码直接使用React.useReducer,这是Mock失效的核心原因
    const [state, dispatch] = React.useReducer(handleUpdates, initState);

    React.useEffect(() => {
        // 关注dispatch的输入值
        dispatch({ type: "fetched data", newName: "Max" });
    }, [])

    return (<div></div>)
}

export default TestReducerComponent;

测试代码

import { render } from '@testing-library/react';
import TestReducerComponent from './TestReducerComponent';
import caller from './caller-Module';

it("react specific test", async () => {
    const mockedDispatcherFunction = jest.fn();

    jest
        .spyOn(caller, 'useReducer')
        .mockImplementationOnce((reducer, initialState) => [initialState, mockedDispatcherFunction]);

    render(<TestReducerComponent name={"Peter"}></TestReducerComponent>)

    // 原断言参数错误:组件dispatch的是newName,而非initValues包裹的结构
    expect(mockedDispatcherFunction).toHaveBeenCalledWith({ type: 'fetched data', initValues: { newName: "Max" } });
});

caller-Module 代码

import { useReducer } from "react";

const caller = { useReducer }

export default caller;

问题原因与解决方案

核心问题

  1. Mock对象不匹配:组件中直接调用React.useReducer,但测试里Mock的是caller.useReducer,两者不是同一个引用,导致Mock无法拦截组件内的useReducer调用。
  2. 断言参数错误:测试中的断言使用了initValues: {newName: "Max"},但组件实际dispatch的是newName: "Max",参数结构不匹配。

修复步骤

  1. 修改组件的useReducer导入方式:
    在组件中导入caller模块的useReducer,替换原有的React.useReducer:

    import caller from './caller-Module';
    
    // ...
    
    const [state, dispatch] = caller.useReducer(handleUpdates, initState);
    
  2. 修正测试中的断言参数:
    将断言的参数改为组件实际dispatch的结构:

    expect(mockedDispatcherFunction).toHaveBeenCalledWith({ type: 'fetched data', newName: "Max" });
    
  3. 修正组件名称拼写:
    原组件定义为TestRedcuerComponent(少了字母d),测试中使用TestReducerComponent,需统一名称避免渲染错误。

内容的提问来源于stack exchange,提问作者Feuerschinken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:45:20