从CRA迁移到Vite后,Vitest测试中Emotion css props无法获取theme对象
解决Vitest测试中Emotion Theme为空对象的问题
核心原因
测试环境未通过ThemeProvider注入主题上下文,而运行时应用的根组件通常会包裹ThemeProvider,导致测试时组件无法获取主题数据。此外需确认Vitest是否正确应用了Emotion的Babel转换配置。
解决方案
1. 在测试全局配置中添加ThemeProvider包裹
修改src/setupTests.ts,将所有测试组件自动包裹在Emotion的ThemeProvider中,确保主题上下文可用:
import { ThemeProvider } from '@emotion/react'; import { render } from '@testing-library/react'; import { theme } from './path/to/your/theme'; // 替换为项目实际主题文件路径 // 重写render方法,默认注入主题 export const render = (ui: React.ReactElement, options?: Parameters<typeof render>[1]) => { return render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>, options); };
之后在测试文件中使用这个自定义render方法渲染组件,即可获取完整主题对象。
2. 确认Vitest正确应用Emotion的Babel插件
虽然Vite配置中已添加@emotion/babel-plugin,需确保Vitest在测试模式下加载该配置。可在Vitest配置中显式指定Babel选项:
修改vite.config.ts的test字段:
test: { globals: true, environment: 'happy-dom', setupFiles: './src/setupTests.ts', // 显式配置Babel插件 babel: { plugins: ['@emotion/babel-plugin'], }, }
若使用React 17+,也可通过jsxImportSource配置Emotion,无需依赖Babel插件:
在tsconfig.json中添加:
{ "compilerOptions": { "jsxImportSource": "@emotion/react" } }
同时调整Vite React插件配置:
react({ jsxImportSource: '@emotion/react', })
3. 手动包裹测试组件(局部方案)
若未使用全局自定义render方法,可在单个测试中手动包裹主题上下文:
import { ThemeProvider } from '@emotion/react'; import { render } from '@testing-library/react'; import SomeComponent from './Component'; import { theme } from './path/to/your/theme'; test('渲染组件并正确获取主题', () => { render( <ThemeProvider theme={theme}> <SomeComponent /> </ThemeProvider> ); // ... 断言逻辑 });
总结
最常见的原因是测试环境缺少主题上下文注入,通过全局或局部添加ThemeProvider即可解决。同时需确保Emotion的编译配置在测试环境中正常生效,避免因转换不完整导致主题无法传递。
内容的提问来源于stack exchange,提问作者Dimitris Karagiannis
相关产品推荐
相关产品推荐

