Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest.fn() not registering mock implementation

Tags:

jestjs

Using Jest 27.5.1

I'm writing tests and I need to see that a function is called, but I don't want it to actually do any of its normal operations. That's pretty much a textbook case for mocking. The problem is that I need this function to return a promise for the purpose of the test and then allow me to resolve that promise in the test with appropriate values. I can successfully mock the low-level XMLHttpRequest stuff and I do for another test, but that's deeper in the stack than I want to go for this test. For one thing, I probably want to replace the way the function I'm currently trying to mock functions at some point.

So...

import * as Network from './Network';

let mockResolver = null;
let mockPromise = null;

const mockGetFromPath = jest.fn().mockImplementation((path, query) => {
    debugger;
});

jest.mock('./Network', () => {
    const originalModule = jest.requireActual('./Network');

    return {
        __esModule: true,
        ...originalModule,
        getFromPath: jest.fn((path, query) => {
            debugger;
            return mockPromise;
        }),
        postToPath: (path, body, query) => mockPromise,
    };
});

I tried a few experiments using debugger statements and such. The function at the top (mockGetFromPath) is such an experiment. Calling mockGetFromPath in a test never runs that implementation.

In the mocked module, if I don't use jest.fn to mock the function, the implementation works perfectly, but of course, it doesn't track calls or call parameters. If I use jest.fn, it just never calls the desired implementation.

Everything I've found in the documentation for Jest says this should work. But it's not working. It never calls the mock implementation, just a generic mock function. I've tried a few other ideas and read a half-dozen answers on StackOverflow, but none of them seems to address the issue I'm having.

like image 938
aikimcr Avatar asked Nov 01 '25 16:11

aikimcr


1 Answers

I was having this issue and discovered my Jest config had resetMocks: true, which means the mock implementation you pass in will be cleared before every test! The default is false, so just ensure it's not set to true if that is undesired behavior. That should allow you to do this:

import { get } from Network;

jest.mock('./Network', () => ({
  __esModule: true,
  ...jest.requireActual('./Network'),
  getFromPath: jest.fn().mockResolvedValue({ name: 'Joe' }),
}));

describe('get', () => {
  test('works', async () => {
    const response = await get('/user-named-joe');

    expect(getFromPath).toHaveBeenCalledTimes(1);
    expect(response).toBe({ name: 'Joe' });
  });
})

P.S. if you do want/have resetMocks set to true, the pattern is very similar. You just mock the implementation in the test itself:

import { get } from Network;

jest.mock('./Network', () => ({
  __esModule: true,
  ...jest.requireActual('./Network'),
  getFromPath: jest.fn(),
}));

describe('get', () => {
  test('works', async () => {
    getFromPath.mockResolvedValue({ name: 'Joe' });

    const response = await get('/user-named-joe');

    expect(getFromPath).toHaveBeenCalledTimes(1);
    expect(response).toBe({ name: 'Joe' });
  });
})
like image 169
Christian Jensen Avatar answered Nov 03 '25 22:11

Christian Jensen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!