React中Mock TailwindCSS遇渲染错误,Formik表单测试问题求助
问题分析与解决方案
错误根源
从你提供的错误截图来看,报错为 TypeError: Cannot read properties of undefined (reading 'firstName'),直接原因是Input组件尝试访问 formik.values.firstName 时,formik 对象本身为 undefined。这个错误和TailwindCSS无关,是Formik实例的传递或Mock逻辑出错导致的。
具体修复步骤
1. 恢复Formik实例的传递
你的测试代码中注释掉了formik={mockFormik}属性,导致PgProfileData组件无法拿到Formik实例,进而子组件Input访问formik相关属性时抛出错误。直接取消注释即可:
const { asFragment } = render( <PgProfileData formik={mockFormik} /> );
2. 完善Mock Formik对象的属性
Input组件用到了formik.errors.firstName,但你当前的mockFormik中缺少errors字段,需要补充避免潜在错误:
const mockFormik = { values: { /* ... 现有值 ... */ }, touched: {}, errors: {}, // 新增errors字段 handleChange: jest.fn(), handleBlur: jest.fn(), setFieldValue: jest.fn(), handleSubmit: formSubmitHandler, isSubmitting: false };
3. 处理i18n翻译的Mock
Input组件中使用了t('chChampionForm.firstName'),如果你的项目用了react-i18next,需要MockuseTranslation钩子,否则t函数会未定义:
// 在测试文件顶部添加 jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key) => key }), }));
4. 关于TailwindCSS的Mock(非当前错误原因)
测试React组件时,TailwindCSS的类名不会影响JS逻辑执行,无需额外Mock。如果担心样式干扰快照,可以在Jest配置中忽略CSS文件:
在jest.config.js中添加:
module.exports = { moduleNameMapper: { '\\.(css|scss|sass)$': 'identity-obj-proxy', }, };
需要先安装identity-obj-proxy依赖:
npm install --save-dev identity-obj-proxy
修正后的测试代码片段
// 顶部添加必要的Mock jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key) => key }), })); describe('FrChampionForm', () => { beforeEach(() => { jest.clearAllMocks(); }); it('submits the form when Continue button is clicked', async () => { const formSubmitHandler = jest.fn(); const mockFormik = { values: { firstName: '', familyName: '', birthYear: '', // ... 其他字段保持不变 }, touched: {}, errors: {}, // 新增errors字段 handleChange: jest.fn(), handleBlur: jest.fn(), setFieldValue: jest.fn(), handleSubmit: formSubmitHandler, isSubmitting: false }; const mockContextValue = [{ profile: { type: 'fr' } }]; React.useContext.mockReturnValue(mockContextValue); const { asFragment } = render( <PgProfileData formik={mockFormik} // 恢复传递formik实例 /> ); expect(asFragment()).toMatchSnapshot(); // 后续的用户交互和断言逻辑保持不变 userEvent.type(screen.getByTestId('first-name-input'), 'John'); // ... fireEvent.click(screen.getByText('Continue')); await waitFor(() => { expect(screen.queryByText('Continue')).toBeNull(); // ... }); }); });
内容的提问来源于stack exchange,提问作者user8989
相关产品推荐
相关产品推荐

