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

React依赖状态的组件测试失败:回调调用结果不符合预期

问题排查:React组件测试失败原因及解决办法

问题描述

测试React组件时遇到失败,推测是输入新字符后上游状态更新导致组件重渲染丢失之前的数据。

组件代码

export const MyTest = (
    {value, updateCallback}: {
        value: string,
        updateCallback: (value: string) => void
    }) => {
    return (
        <>
            <label htmlFor="my-test">My Test</label>
            <input value={value} type="text" id="my-test" onChange={(e) => {
                updateCallback(e.target.value);
                console.log(e.target.value);
            }}/>
        </>
    );
}

测试代码

test("test", async () => {
    const user = userEvent.setup();

    const updateCallback = vi.fn()
    render(<MyTest value="" updateCallback={updateCallback}/>)

    const input = screen.getByLabelText("My Test");

    await act(async () => await user.type(input, "my-value"));

    expect(updateCallback).toHaveBeenLastCalledWith("my-value");
})

测试失败输出

m
y
-
v
a
l
u
e

AssertionError: expected last "spy" call to have been called with [ 'my-value' ]

失败原因

测试中组件的value属性始终固定为初始值"",没有随着updateCallback的调用同步更新。当user.type输入字符时,每输入一个字符都会触发onChange调用updateCallback,但组件的value没有更新,导致组件重渲染后输入框回到空值,最终updateCallback的最后一次调用仅传入单个字符"e",而非预期的完整字符串"my-value"。

解决方案

在测试中模拟真实的状态更新逻辑,用状态变量保存输入值,每次updateCallback被调用时更新状态并同步传给组件:

修改后的测试代码

import { useState } from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MyTest } from './MyTest';

test("test", async () => {
    const user = userEvent.setup();
    const updateCallback = vi.fn();

    // 模拟真实的状态管理逻辑
    const TestWrapper = () => {
        const [inputValue, setInputValue] = useState("");
        const handleUpdate = (value: string) => {
            setInputValue(value);
            updateCallback(value);
        };
        return <MyTest value={inputValue} updateCallback={handleUpdate}/>;
    };

    render(<TestWrapper />);
    const input = screen.getByLabelText("My Test");

    await user.type(input, "my-value");

    expect(updateCallback).toHaveBeenLastCalledWith("my-value");
})

修改说明

  • 用useState创建状态变量inputValue,模拟组件上游的状态管理逻辑
  • 定义handleUpdate函数,既更新状态变量,又调用mock的updateCallback
  • 渲染组件时将最新的inputValue传给value属性,确保输入框的值能随输入内容累积

这样修改后,测试时输入框会正确同步每一次输入的内容,最终updateCallback的最后一次调用会传入完整的"my-value",测试即可通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:22:58