如何Mock Recoil自定义Hook?测试时列表渲染始终为空的问题
问题分析与解决方案
核心问题:组件渲染文本而非真实DOM节点
你的UsersList组件中,map返回的是模板字符串而非JSX元素:
{names.map((name) => `<li key={name}>${name}</li>`)}
React会将这段字符串直接渲染为文本内容,不会生成真正的<li>标签,因此screen.queryAllByRole('listitem')找不到任何符合要求的DOM节点,导致长度为0。
修复步骤
1. 修正组件的JSX写法
把模板字符串改为JSX元素:
export const UsersList = () => { const names = useUsersList(); return ( <ul> {names.map((name) => ( <li key={name}>{name}</li> ))} </ul> ); };
2. 优化测试方案(可选,更贴近真实场景)
如果不想依赖Mock自定义Hook,可以直接通过RecoilRoot的initialState初始化atom值,避免Mock带来的潜在问题:
import { usersState } from '../hooks/useUsersList'; import { UsersList } from '../components/UsersList'; import { render, screen } from '@testing-library/react'; import { RecoilRoot } from 'recoil'; describe('when filled', () => { const names = ['Moses', 'Jacob']; it('should render the names', () => { render( <RecoilRoot initialState={({ set }) => { set(usersState, names); }} > <UsersList /> </RecoilRoot> ); const items = screen.queryAllByRole('listitem'); expect(items).toHaveLength(names.length); }); });
3. 确保Mock方式正确(如果坚持用Mock)
如果你继续使用Mock自定义Hook,要确保:
- 正确导入被Mock的
useUsersList - Jest的Mock路径与文件实际路径匹配
import { useUsersList } from '../hooks/useUsersList'; import { UsersList } from '../components/UsersList'; import { render, screen } from '@testing-library/react'; import { RecoilRoot } from 'recoil'; jest.mock('../hooks/useUsersList'); describe('when filled', () => { const names = ['Moses', 'Jacob']; it('should render the names', () => { useUsersList.mockReturnValue(names); render( <RecoilRoot> <UsersList /> </RecoilRoot> ); const items = screen.queryAllByRole('listitem'); expect(items).toHaveLength(names.length); }); });
内容的提问来源于stack exchange,提问作者Samuel A. Souza
相关产品推荐
相关产品推荐

