React Jest中Mock自定义Hook时返回值为undefined的问题
问题:Mock React自定义Hook后返回文本为undefined
尝试Mock React自定义Hook,但Mock函数返回的文本始终为undefined,测试报错信息如下:
Test for selected filter section › Test selected filter label expect(element).toHaveTextContent() Expected element to have text content: 2 filters selected Received: 2 undefined
相关组件代码(my-component/index.tsx)
import React from 'react'; import customHook from '@path/to/customHook'; type Props = { checkedItems: LabelProps[]; handleClearAll: () => void; }; const MyComponent: React.FC<Props> = ({ checkedItems, handleClearAll }) => { const { content: productLabels } = customHook(); return ( <> {checkedItems.length > 0 && ( <div data-testId="selected-filter-container"> <div data-testId="selected-filter-lable-container"> <p data-testId="selected-filter-label"> {`${checkedItems.length} ${productLabels?.filtersSelected?.value}`} </p> <div data-testId="clearAll-label" onClick={handleClearAll}> {productLabels?.clearAll?.value} </div> </div> </div> )} </> ); }; export default MyComponent;
相关测试代码(my-component/index.test.tsx)
import { render, screen } from '@testing-library/react'; import React from 'react'; import MyComponent from './index'; const labels = { content: { clearAll: { key: 'data.clearAll', value: 'Clear all', }, filtersSelected: { key: 'data.filtersSelected', value: ' filters selected', }, }, }; describe('Test for selected filter section', () => { const checkedItemsMock = [ { name: 'Mock name 1', slug: 'mock-slug-1', value: 'Mock value 1', }, { name: 'Mock name 2', slug: 'mock-slug-2', value: 'Mock value 2', }, ]; const handleClearAllMock = jest.fn(); const handleRemoveItemMock = jest.fn(); jest.mock('@path/to/customHook', () => { return { // __esModule: true, default: () => labels, }; }); // success it('Test selected filter container', () => { render( <MyComponent checkedItems={checkedItemsMock} handleClearAll={handleClearAllMock} handleRemoveItem={handleRemoveItemMock} />, ); const elem = screen.getByTestId('selected-filter-container'); expect(elem).toBeInTheDocument(); }); // success it('Test selected filter label container', () => { render( <MyComponent checkedItems={checkedItemsMock} handleClearAll={handleClearAllMock} handleRemoveItem={handleRemoveItemMock} />, ); const elem = screen.getByTestId('selected-filter-lable-container'); expect(elem).toBeInTheDocument(); }); // fail it('Test selected filter label', () => { render( <MyComponent checkedItems={checkedItemsMock} handleClearAll={handleClearAllMock} handleRemoveItem={handleRemoveItemMock} />, ); const totalReviews = `${checkedItemsMock.length} ${labels?.content?.filtersSelected?.value}`; expect(screen.getByTestId('selected-filter-label')).toHaveTextContent(totalReviews); }); });
解决方法
问题出在Jest模拟ES模块默认导出的配置上,修改测试代码中的jest.mock部分,启用__esModule: true即可:
jest.mock('@path/to/customHook', () => { return { __esModule: true, // 取消注释这一行 default: () => labels, }; });
原因说明
使用jest.mock模拟ES模块的默认导出时,必须显式设置__esModule: true标识。否则Jest会将默认导出当作模块的普通属性处理,导致组件中调用customHook()无法正确获取预期的content结构,最终productLabels?.filtersSelected?.value返回undefined。
内容的提问来源于stack exchange,提问作者Shan Biswas
相关产品推荐
相关产品推荐

