如何在Vitest中为不同测试用例模拟单个导入变量
问题原因
你当前的mock方式是将isRootPresent导出为固定值,后续修改mocks.isRootPresent不会同步到导出的常量——这是一次值拷贝,模块导出后就不会再更新这个值了。
解决方案一:用Getter实现动态Mock
修改mock逻辑,通过getter让每次访问isRootPresent时都取最新的mock值:
import { render, screen } from '@testing-library/react'; import { afterEach } from 'vitest'; const mocks = vi.hoisted(() => { return { isRootPresent: true, } }) vi.mock('./utils.ts', () => { return { // 使用getter动态返回mock值 get isRootPresent() { return mocks.isRootPresent; } } }) describe("App component", () => { // 每次测试后重置mock状态 afterEach(() => { mocks.isRootPresent = true; }) it("should render Root is present text", () => { mocks.isRootPresent = true; render(<App/>); expect(screen.getByTestId('test-heading')).toBeInTheDocument(); expect(screen.getByTestId('test-heading').textContent).toBe('Root is present'); }) it("should not render Root is present text", () => { mocks.isRootPresent = false; render(<App/>); // 用queryByTestId避免找不到元素时抛出错误 expect(screen.queryByTestId('test-heading')).not.toBeInTheDocument(); }) })
解决方案二:直接Mock DOM环境(更贴近真实逻辑)
既然isRootPresent的本质是判断DOM中是否存在#root元素,直接模拟DOM场景,无需mock整个utils模块:
import { render, screen } from '@testing-library/react'; import { afterEach, vi } from 'vitest'; describe("App component", () => { afterEach(() => { // 清理DOM,避免测试间污染 const rootEl = document.getElementById('root'); if (rootEl) rootEl.remove(); // 重置模块缓存,确保每次测试重新计算isRootPresent vi.resetModules(); }) it("should render Root is present text", async () => { // 在DOM中添加#root元素 const rootEl = document.createElement('div'); rootEl.id = 'root'; document.body.appendChild(rootEl); // 重新导入App(模块缓存会保留之前的isRootPresent值) const { App } = await import('./App'); render(<App/>); expect(screen.getByTestId('test-heading')).toBeInTheDocument(); }) it("should not render Root is present text", async () => { // DOM中没有#root元素,直接重新导入App const { App } = await import('./App'); render(<App/>); expect(screen.queryByTestId('test-heading')).not.toBeInTheDocument(); }) })
补充说明
- 方案一的getter确保每次组件访问
isRootPresent时,都会获取最新的mock值,解决了值拷贝导致的更新不生效问题。 - 方案二更贴近真实业务逻辑,模拟了实际的DOM场景而非直接mock常量。
- 检查元素是否不存在时,推荐用
queryByTestId,getByTestId在找不到元素时会抛出错误,导致测试失败。
内容的提问来源于stack exchange,提问作者animatio
相关产品推荐
相关产品推荐

