求助:Jest中Mock ES6模块命名导出失败的问题
在Jest中Mock ES6模块命名导出失败的问题
我之前成功实现过在Jest里Mock ES6模块的命名导出,但现在找不到旧代码了。参考Stack Overflow相关问题后还是没能成功Mock。
我的ES6模块CatService代码如下:
export default "default" export const getCatFact = () => ({fact: "cats are quadrupeds"});
这个模块被下面的React组件使用:
import React from "react"; import { getCatFact } from "./CatService"; const Component = () => { const {fact} = getCatFact(); return <div data-testid="my-div">{fact}</div> } export default Component;
我试过参考Andy的已采纳答案来Mock:
import React from "react"; import { render, screen } from "@testing-library/react"; import '@testing-library/jest-dom' import Component from "./Component"; test("mock an es6 module", async () => { const mockCatFact = jest.fn(); mockCatFact.mockImplementation(() => ({fact: "mocked"})); jest.mock('./CatService', () => ({ __esModule: true, default: "mockedDefaultExport", getCatFact: mockCatFact })); render( <Component /> ); const myDiv = await screen.findByTestId("my-div") expect(myDiv).toHaveTextContent("mocked");//失败!值未被Mock });
也试过类似falsarella的方法:
import React from "react"; import { render, screen } from "@testing-library/react"; import '@testing-library/jest-dom' import Component from "./Component"; import { getCatFact } from "./CatService"; test("mock an es6 module", async () => { getCatFact.mockImplementation(() => ({fact: "mocked"})); // 报错:"TypeError: _CatService.getCatFact.mockImplementation is not a function" render( <Component /> ); const myDiv = await screen.findByTestId("my-div") expect(myDiv).toHaveTextContent("mocked");//失败!值未被Mock });
两种方法都没生效,还是拿到未Mock的值。请问我哪里错了?
问题原因及解决方案
第一种方法失效原因
jest.mock是被Jest自动提升到模块顶部执行的,你在测试函数里定义的mockCatFact在jest.mock执行时还未初始化,导致Mock的是一个无效变量,自然无法生效。
修正后的第一种方法
把jest.mock移到模块顶层,直接在Mock工厂函数中定义mock逻辑,或者后续动态修改返回值:
import React from "react"; import { render, screen } from "@testing-library/react"; import '@testing-library/jest-dom' import Component from "./Component"; import { getCatFact } from "./CatService"; // 移到模块顶层,Jest会自动提升执行 jest.mock('./CatService', () => ({ __esModule: true, default: "mockedDefaultExport", getCatFact: jest.fn() })); test("mock an es6 module", async () => { // 动态设置mock返回值 getCatFact.mockReturnValue({fact: "mocked"}); render(<Component />); const myDiv = await screen.findByTestId("my-div") expect(myDiv).toHaveTextContent("mocked"); });
第二种方法失效原因
直接调用getCatFact.mockImplementation报错,是因为原方法并非jest mock函数。可以用jest.spyOn来替换目标方法,无需Mock整个模块:
import React from "react"; import { render, screen } from "@testing-library/react"; import '@testing-library/jest-dom' import Component from "./Component"; import * as CatService from "./CatService"; test("mock an es6 module with spyOn", async () => { // 用spyOn创建mock函数并替换原方法 const mockGetCatFact = jest.spyOn(CatService, 'getCatFact') .mockImplementation(() => ({fact: "mocked"})); render(<Component />); const myDiv = await screen.findByTestId("my-div") expect(myDiv).toHaveTextContent("mocked"); // 测试结束后恢复原方法,避免影响其他测试 mockGetCatFact.mockRestore(); });
内容的提问来源于stack exchange,提问作者Steve D
相关产品推荐
相关产品推荐

