0

I have my test case file set up like this:

const request = require("supertest");
const app = require("../app");

jest.mock("./addFunc", () => ({
    addNumbers: jest.fn()
}));
...
test("Testing add function with double result", () => {
    addNumbers.mockImplentation((a, b) =>
        return 2 * (a + b));
    let res = await request(app).post("/addNumbers").send({
        a: 1,
        b: 2
    });
    expect(res.body.result).toBe(6);
});
...
test("Testing add function with half result", () => {
    addNumbers.mockImplentation((a, b) =>
        return (a - b) / 2);
    let res = await request(app).post("/addNumbers").send({
        a: 6,
        b: 2
    });
    expect(res.body.result).toBe(2);
});
...

The addNumbers API I am calling contains addNumbers function, which I want to mock with different implementations for different test cases like above. I took help from the most-voted answer of How to change mock implementation on a per single test basis?

But as I ran the test case, it threw error inside the test case that addNumbers is not defined. However, if I don't write mockImplementation inside test case and mock the addNumbers on top of the file, then it works fine. But in that case how would I rewrite the mock for a different test case?

I am not able to figure it out because addNumbers has already been defined on top of the file.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
NodeFriend
  • 45
  • 5
  • You never imported or declared `addNumbers` – Konrad Aug 22 '23 at 11:56
  • ok, but how do I overwrite/rewrite the mock created at the top of the file with ``jest.mock`` for specific test cases. Is it possible? – NodeFriend Aug 22 '23 at 11:58
  • I would move `jest.mock...` inside each test – Konrad Aug 22 '23 at 11:59
  • Is there any cleaner solution than moving jest.mock inside each test case? – NodeFriend Aug 22 '23 at 12:01
  • Just `jest.mock("./addFunc");` (which has to be _outside_ the tests @Konrad, otherwise it doesn't get hoisted) and also `const { addNumbers } = require("./addFunc");` to get access to the test double. Although based on what you've posted you really shouldn't be mocking it - your test is mostly of the test double. – jonrsharpe Aug 22 '23 at 12:39
  • @Konrad moving jest.mock to each test case doesn't work. I have tried it. In that case, mock function does not have any effect and the original function gets called instead. – NodeFriend Aug 22 '23 at 12:40
  • @jonrsharpe what should be the approach then? – NodeFriend Aug 22 '23 at 12:41
  • 1
    ... _don't_ mock it. Just write the test with the expectation based on the actual behaviour (presumably `{ a: 1, b: 2 }` -> `{ result: 3 }`). Whatever you're doing you at least need to rename the tests, because the one thing you're **not** doing is _"Testing add function"_ - it's not involved at all, _you've mocked it out_. ([Here's](https://blog.jonrshar.pe/2023/May/23/js-tdd-ohm.html) an article I wrote on a TDD approach to an Express API you might find useful.) – jonrsharpe Aug 22 '23 at 12:42

1 Answers1

2

You can import the file you are mocking and then reference addNumbers from within the file, instead of using it directly. Here's an example of your updated code:

const request = require("supertest");
const app = require("../app");
const addFunc = require("./addFunc");

jest.mock("./addFunc", () => ({
    addNumbers: jest.fn()
}));
...
test("Testing add function with double result", () => {
    addFunc.addNumbers.mockImplementation((a, b) =>
        return 2 * (a + b));
    let res = await request(app).post("/addNumbers").send({
        a: 1,
        b: 2
    });
    expect(res.body.result).toBe(6);
});
...
test("Testing add function with half result", () => {
    addFunc.addNumbers.mockImplementation((a, b) =>
        return (a - b) / 2);
    let res = await request(app).post("/addNumbers").send({
        a: 6,
        b: 2
    });
    expect(res.body.result).toBe(2);
});

Note: I fixed a typo in the mockImplementation, you lost the "me"

Hope it helps!