如何在Vitest中每次测试后重置导入的文件?
问题解决:Vitest测试中模块状态无法重置及mock导致函数失效
你的问题出在vi.mock的使用方式上——默认情况下,vi.mock会把目标模块的所有导出函数替换成空的mock函数,完全跳过原函数的逻辑。所以你调用的setValue和getValue都是没有实际功能的mock,自然setValue不会修改内部的settings,getValue返回undefined。
下面给你两种可行的解决方案:
方案一:用vi.resetModules重置模块缓存(推荐,无需修改原代码)
通过动态导入模块,并在每次测试后重置模块缓存,这样每次测试都会加载全新的模块实例,内部的settings会自动回到初始状态:
import { afterEach, describe, expect, it, vi } from "vitest"; describe("setValue", () => { // 每次测试后清除模块缓存 afterEach(() => { vi.resetModules(); }); it("test1", async () => { // 动态导入模块 const { setValue, getValue } = await import("./index.js"); setValue('en'); expect(getValue()).toBe('en'); }); it("test2", async () => { const { getValue } = await import("./index.js"); // 验证状态已重置为空字符串 expect(getValue()).toBe(''); }); });
方案二:手动mock并保留原函数逻辑
如果一定要用vi.mock,可以手动让mock函数调用原实现,同时添加重置状态的方法:
修改测试文件如下:
import { afterEach, describe, expect, it, vi } from "vitest"; vi.mock("./index.js", async () => { // 导入原模块的真实实现 const original = await vi.importActual("./index.js"); // 维护一份独立的settings状态,方便重置 const settings = { value: '' }; return { ...original, setValue: (val) => { settings.value = val; }, getValue: () => settings.value, // 添加重置方法 __resetSettings: () => { settings.value = ''; } }; }); describe("setValue", () => { let module; beforeEach(async () => { module = await import("./index.js"); }); afterEach(() => { // 调用重置方法恢复初始状态 module.__resetSettings(); }); it("test1", () => { module.setValue('en'); expect(module.getValue()).toBe('en'); }); it("test2", () => { expect(module.getValue()).toBe(''); }); });
关键说明
vi.mock默认生成的mock函数没有任何实际逻辑,只是占位符,不能直接用来测试原函数的功能。vi.resetModules会清除Node.js的模块缓存,让下次import重新加载模块,从而重置模块内部的私有状态。
内容的提问来源于stack exchange,提问作者user64675
相关产品推荐
相关产品推荐

