从Jest迁移至Vitest时vi.mock生命周期引发测试报错问题
Jest迁移Vitest:第二个测试用例vi.spyOn报错"setInput does not exist"的解决方案
问题根源
问题核心在于vi.restoreAllMocks()在Vitest和Jest中的行为差异:
- Jest的
restoreAllMocks仅清除mock的调用记录,不会改动mock的实现逻辑 - Vitest的
vi.restoreAllMocks()会完全重置所有mock的实现,包括你通过vi.mock定义的MockStep的mockImplementation。第一个测试执行后,afterEach里的restoreAllMocks把MockStep的构造函数打回原形,导致第二个测试时new MockStep()返回空对象,自然找不到setInput方法。
修复方案
最简洁的解决方式是把vi.restoreAllMocks()换成vi.clearAllMocks():
vi.clearAllMocks()只会清除mock的调用记录、实例和结果,不会改动mock的实现逻辑,刚好匹配你的测试需求。
修改后的代码
import {describe, beforeEach, afterEach, test, expect, vi} from "vitest"; import {Step as MockStep} from "../step"; vi.mock("../step", () => { return { Step: vi.fn().mockImplementation(() => { return { setInput() {}, }; }), }; }); describe("Step", () => { let step; beforeEach(() => { step = new MockStep(); }); afterEach(() => { // 替换为clearAllMocks,只清调用记录不重置实现 vi.clearAllMocks(); }); test("first", () => { vi.spyOn(step, "setInput"); expect(true).toBe(true); }); test("second", () => { vi.spyOn(step, "setInput"); // 现在可正常执行 expect(true).toBe(true); }); });
备选方案(若必须用restoreAllMocks)
如果你的测试场景确实需要保留vi.restoreAllMocks(),可以在beforeEach里重新绑定mock实现,避免被重置:
describe("Step", () => { let step; beforeEach(() => { // 每次测试前重新设置mock实现 MockStep.mockImplementation(() => { return { setInput() {}, }; }); step = new MockStep(); }); afterEach(() => { vi.restoreAllMocks(); }); // ...测试用例不变 });
内容的提问来源于stack exchange,提问作者n8o
相关产品推荐
相关产品推荐

