如何阻止Jest.mock提升,仅在单个单元测试中应用指定Mock?
解决Jest仅在单个测试中Mock导入组件的问题
由于jest.mock会被Jest自动提升到模块顶部,无论你把它写在describe还是test块内,所有测试都会共享这个Mock。要实现仅在指定测试中使用Mock,有两种可靠方案:
方案1:使用jest.doMock + 动态导入
jest.doMock不会被Jest提升,仅在调用位置生效,结合jest.resetModules重置模块缓存,就能实现隔离Mock。
describe("My test suite here", () => { beforeEach(() => { jest.clearAllMocks(); jest.resetModules(); // 每次测试前清空模块缓存,避免Mock污染 }); test("Renders dialog1", async () => { // 动态导入被测试组件,使用真实的Dialog const MyComponent = (await import("../path/to/your/component")).default; render(<MyComponent />); // 你的断言逻辑 }); test("Renders dialog2", async () => { const MyComponent = (await import("../path/to/your/component")).default; render(<MyComponent />); // 你的断言逻辑 }); test("Renders dialog with mock", async () => { // 仅在此测试中Mock目标组件 jest.doMock("@components/components-chat-dialog", () => ({ ...jest.requireActual("@components/components-chat-dialog"), Dialog: jest.fn().mockImplementation(({ header, content }) => ( <div> <div data-testid="dialog-header">{header}</div> <div data-testid="dialog-content">{content}</div> </div> )), })); // 动态导入被测试组件,此时会使用上面的Mock const MyComponent = (await import("../path/to/your/component")).default; render(<MyComponent />); // 你的断言逻辑 expect(screen.getByTestId("dialog-header")).toBeInTheDocument(); }); test("Renders dialog3", async () => { const MyComponent = (await import("../path/to/your/component")).default; render(<MyComponent />); // 你的断言逻辑 }); });
方案2:使用jest.spyOnMock单个导出
如果仅需要Mock模块中的单个导出(比如这里的Dialog),用jest.spyOn更简洁,测试后直接恢复原实现即可。
import MyComponent from "../path/to/your/component"; describe("My test suite here", () => { beforeEach(() => { jest.clearAllMocks(); }); test("Renders dialog1", () => { render(<MyComponent />); // 你的断言逻辑 }); test("Renders dialog2", () => { render(<MyComponent />); // 你的断言逻辑 }); test("Renders dialog with mock", () => { // 创建Spy并替换Dialog的实现 const mockDialog = jest.spyOn(require("@components/components-chat-dialog"), "Dialog") .mockImplementation(({ header, content }) => ( <div> <div data-testid="dialog-header">{header}</div> <div data-testid="dialog-content">{content}</div> </div> )); render(<MyComponent />); // 你的断言逻辑 expect(screen.getByTestId("dialog-header")).toBeInTheDocument(); // 测试结束后恢复原Dialog组件 mockDialog.mockRestore(); }); test("Renders dialog3", () => { render(<MyComponent />); // 你的断言逻辑 }); });
内容的提问来源于stack exchange,提问作者HackerMan33453
相关产品推荐
相关产品推荐

