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

如何在Jest测试中验证props传入的useState的set函数是否被调用?

解决React组件测试中setOrder未被调用的问题

问题背景

React组件中包含异步处理函数:

const changeOrder = () => { /* WebSocket 请求逻辑 */ };

const handleArrow = async () => {
    const res = await changeOrder(side, headingOrder, config);
    if (res !== undefined) setOrder(res);
};

其中setOrder是通过props传入的useState更新函数。测试时希望验证setOrder是否被调用,但最后断言expect(setOrder).toHaveBeenCalled()失败,错误信息显示调用次数为0,且已确认res !== undefined条件成立。

测试代码如下:

// WebSocket Mock-up
let ws: WS;
beforeEach(async () => {
    ws = new WS("ws://localhost:8764", { jsonProtocol: true });
    new WebsocketClient("localhost", 8764);
    await ws.connected;
});
afterEach(() => {
    WS.clean();
});

describe("The ChangeOrderArrow component", () => {
    it("should render left arrow and can send a request to change the heading order", async () => {
        const setOrder = jest.fn();
        render(
            <ChangeOrderArrow
                setOrder={setOrder}
            />,
        );

        fireEvent.click(screen.getByTestId("left-heading-button"));

        const req: { request: RequestMessage } = (await ws.nextMessage) as { request: RequestMessage };
        const uuid = req.request.path.split("/")[2];

        expect(req.request.options.value).toEqual(359);

        act(() => {
            ws.send(responseChangeOrderArrow(uuid));
        });

        expect(setOrder).toHaveBeenCalled();
    });
});

解决思路

1. 等待React异步更新完成

handleArrow是异步函数,WebSocket响应触发组件状态更新也是异步的,直接断言时React可能还未完成状态更新。改用waitFor包裹断言,等待异步操作完成:

import { waitFor } from '@testing-library/react';

// ... 其他代码不变

act(() => {
    ws.send(responseChangeOrderArrow(uuid));
});

await waitFor(() => {
    expect(setOrder).toHaveBeenCalled();
});

2. 检查act的覆盖范围

如果ws.send内部是异步触发组件更新,单纯用act包裹send可能无法覆盖后续的状态更新流程。可以将send和断言都放在waitFor中,或者确保所有状态更新都在act的作用域内。

3. 先隔离测试核心逻辑

暂时Mock掉changeOrder函数,直接返回预期值,测试handleArrow本身的逻辑是否正确,排除WebSocket的干扰:

it("should call setOrder when changeOrder returns a value", async () => {
    const setOrder = jest.fn();
    const mockChangeOrder = jest.fn().mockResolvedValue({ /* 预期返回值 */ });
    
    // 假设组件接收changeOrder作为props,或者通过其他方式注入mock
    render(
        <ChangeOrderArrow
            setOrder={setOrder}
            changeOrder={mockChangeOrder}
        />,
    );

    fireEvent.click(screen.getByTestId("left-heading-button"));
    
    await waitFor(() => {
        expect(setOrder).toHaveBeenCalled();
    });
});

4. 验证WebSocket响应是否正确触发changeOrder的返回

确认ws.send(responseChangeOrderArrow(uuid))发送的响应确实能被组件的WebSocket客户端正确接收,并触发changeOrder返回预期值。可以在测试中添加日志或者断点,检查响应是否被正确处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:12:40