Home > front end >  Can't mock a ES6 imported function in NodeJS
Can't mock a ES6 imported function in NodeJS

Time:11-01

I've been trying for some time to mock the fetchLiveMatches imported function with no success. I've been browsing for some ideas but I think I ran out of it, so I could use some help. Any ideas of what I am doing wrong?

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"
  }
}

Test Error Output

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]

CodePudding user response:

Just posting the solution I found for anyone who eventually is facing the same problem:

First, since I'm using ES6/module imports without Babel I changed the mock function to unstable_mockModule, and then based on the docs I decided to try dynamic imports in test scope after mocking the modules.

If you're using ES module imports then you'll normally be inclined to put your import statements at the top of the test file. But often you need to instruct Jest to use a mock before modules use it. For this reason, Jest will automatically hoist jest.mock calls to the top of the module (before any imports). To learn more about this and see it in action, see this repo.

The test component works with the following code:

import { jest } from "@jest/globals";
import { buildReq, buildRes, buildNext } from "../utils/testingHelper";

describe("Live Controller", () => {
  test("calls fetchLiveMatches function to fetch from external API", async () => {
    jest.unstable_mockModule("../service/live", () => ({
      fetchLiveMatches: jest.fn(() => [])
    }));

    const { getLiveMatches } = await import("./live");
    const { fetchLiveMatches } = await import("../service/live");

    const req = buildReq();
    const res = buildRes();
    const next = buildNext(msg => console.log(msg));

    await getLiveMatches(req, res, next);

    expect(fetchLiveMatches).toHaveBeenCalled();
    expect(res.status).toHaveBeenCalledWith(200);
    expect(res.status).toHaveBeenCalledTimes(1);
  });
});
  • Related