React Testing Library测试:初始渲染与按钮点击时数组长度为2的问题
React组件测试问题:验证usersCards元素数量及解决TypeError错误
问题描述
首次测试React应用,需编写测试用例验证组件中的usersCards数组在初始渲染和点击DEAL按钮时均包含2个元素,但遇到错误:TypeError: Expected container to be an Element, a Document or a DocumentFragment but got string.
不确定组件中的变量是否需要在测试文件中模拟,寻求解决帮助。
组件代码
//imports export default function Home(){ const startHandSize = 2 const [starterDeck, setStarterDeck] = useState(shuffle(deckArray)) const [howManyDealt, setHowManyDealt] = useState(startHandSize) const [total, setTotal] = useState(0) const [ace, setAce] = useState(0) const deal = () => { setHowManyDealt(startHandSize) setStarterDeck(shuffle(deckArray)) setAce(0) } const hit = () => !bust && setHowManyDealt(prev => prev + 1) const usersCards = starterDeck.slice(-howManyDealt) const bust = total > 21; useEffect(() => { setTotal(usersCards.reduce((a, e) => a + e.value, 0) + ace) }, [ace, usersCards]) return( <div> { <> <button data-testid="deal" onClick={deal}>DEAL</button> <button data-testid="hit" disabled={bust} onClick={hit}>HIT</button> <button disabled={bust}>STAND</button> <Total total={total}/> {usersCards.map(card => ( <Card data-testid="test-card" key={card.index} card={card} setTotal={setTotal} total={total} ace={ace} setAce={setAce} /> ))} </>} </div> ) }
测试代码
//Deal button test test("on initial render, two cards are displayed", () => { render(<Home />) const cards = getAllByTestId('test-card') expect(cards.length).toEqual(2) })
解决方案
1. 修复TypeError错误
这个错误的核心原因是未正确使用React Testing Library的查询函数:
- 确保从
@testing-library/react正确导入所需工具函数 - render函数返回的对象包含查询方法,需从返回值中解构获取,而非直接使用全局函数(避免冲突或参数错误)
修正后的测试导入与初始测试代码:
import { render, getAllByTestId } from '@testing-library/react'; import Home from './Home'; test("初始渲染时显示2张卡片", () => { // 从render返回值中解构查询函数 const { getAllByTestId } = render(<Home />); const cards = getAllByTestId('test-card'); expect(cards.length).toEqual(2); });
2. 编写点击DEAL按钮的测试用例
要验证点击按钮后的状态,需模拟按钮点击事件,再次检查卡片数量:
import { render, getAllByTestId, getByTestId, fireEvent } from '@testing-library/react'; import Home from './Home'; test("点击DEAL按钮后仍显示2张卡片", () => { const { getAllByTestId, getByTestId } = render(<Home />); // 验证初始状态 expect(getAllByTestId('test-card').length).toBe(2); // 模拟点击DEAL按钮 fireEvent.click(getByTestId('deal')); // 验证点击后的卡片数量 expect(getAllByTestId('test-card').length).toBe(2); });
3. 关于组件变量的模拟
不需要直接模拟usersCards,但为了测试稳定性,建议模拟外部依赖:
- 如果
shuffle是外部函数(如lodash的shuffle),可以模拟它返回原数组,避免随机打乱导致测试结果不稳定:
import shuffle from 'lodash/shuffle'; // 模拟shuffle函数,不打乱数组 jest.mock('lodash/shuffle', () => jest.fn(arr => arr));
4. 组件内部优化(避免测试异常)
组件中bust变量的定义存在闭包风险,建议改用useMemo确保值随total更新:
import { useMemo } from 'react'; // 替换原bust变量定义 const bust = useMemo(() => total > 21, [total]);
内容的提问来源于stack exchange,提问作者01nowicj
相关产品推荐
相关产品推荐

