NodeJS环境下无法Mock ES6导入函数的问题求助
问题:无法Mock导入的fetchLiveMatches函数
我尝试Mock导入的fetchLiveMatches函数已有一段时间,但始终未成功。查阅相关资料后仍无头绪,希望获得帮助。以下是我的代码及错误信息,请问我哪里出错了?
live.test.js
import * as liveController from "./live"; import { jest } from "@jest/globals"; import * as liveService from "../service/live"; import { buildReq, buildRes, buildNext } from "../utils/testingHelper"; jest.mock("../service/live"); beforeEach(() => { jest.clearAllMocks(); }); describe("Live Controller", () => { test("calls fetchLiveMatches function to fetch from external API", async () => { const req = buildReq(); const res = buildRes(); const next = buildNext(); await liveController.getLiveMatches(req, res, next); expect(next).not.toHaveBeenCalled(); expect(liveService.fetchLiveMatches).toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(500); expect(res.status).toHaveBeenCalledTimes(1); }); });
service/live.js
import axios from "axios"; async function fetchLiveMatches() { // Some hidden code return axios({ method: "get", url: `${API_FOOTBALL_BASE_URL}${GET_EVENTS}${MATCH_LIVE}${WIDGET_KEY}${TIMEZONE}${DETAILS}`, headers: {} }).then(res => res.data); } export { fetchLiveMatches };
jest.config.js
export default { testEnvironment: "jest-environment-node", transform: {} };
package.json
{ "name": "server", "version": "1.0.0", "main": "index.js", "type": "module", "license": "MIT", "dependencies": { "express": "^4.18.2" }, "devDependencies": { "axios": "^1.1.3", "eslint": "^8.26.0", "jest": "^29.2.2", "prettier": "^2.7.1" }, "scripts": { "start": "node --watch index.js", "start:no-watch": "node index.js", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch" } }
测试错误输出
Live Controller › calls fetchLiveMatches function to fetch from external API expect(received).toHaveBeenCalled() Matcher error: received value must be a mock or spy function Received has type: function Received has value: [Function fetchLiveMatches]
解决方案
问题根源是你的项目使用ES模块(package.json中type: module),Jest的jest.mock()自动mock逻辑在ES模块环境下无法直接将导出函数替换为mock函数,导致你调用的还是原函数而非mock。
修复方案一:手动替换为mock函数
直接在测试文件中将fetchLiveMatches替换为Jest mock函数:
import * as liveController from "./live"; import { jest } from "@jest/globals"; import * as liveService from "../service/live"; import { buildReq, buildRes, buildNext } from "../utils/testingHelper"; // 手动将原函数替换为mock liveService.fetchLiveMatches = jest.fn(); beforeEach(() => { jest.clearAllMocks(); }); describe("Live Controller", () => { test("calls fetchLiveMatches function to fetch from external API", async () => { const req = buildReq(); const res = buildRes(); const next = buildNext(); // 可选:如果需要触发res.status(500),让mock函数抛出错误 liveService.fetchLiveMatches.mockRejectedValue(new Error('API请求失败')); await liveController.getLiveMatches(req, res, next); expect(next).not.toHaveBeenCalled(); expect(liveService.fetchLiveMatches).toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(500); expect(res.status).toHaveBeenCalledTimes(1); }); });
修复方案二:使用Jest mock目录
通过创建__mocks__目录来实现自动mock:
- 在
service目录下新建__mocks__/live.js文件:
export const fetchLiveMatches = jest.fn();
- 修改
jest.config.js,添加ES模块兼容配置:
export default { testEnvironment: "jest-environment-node", transform: {}, esModuleInterop: true, moduleNameMapper: { "^../service/live$": "<rootDir>/service/__mocks__/live.js" } };
- 测试文件中保留
jest.mock("../service/live");即可,此时Jest会自动加载mock目录中的函数。
内容的提问来源于stack exchange,提问作者tiagoornelas
相关产品推荐
相关产品推荐

