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
相关产品推荐
相关产品推荐

