Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking nested functions with jest

I have this code;

import { initRepo, getOrganisationsRepo } from "Repositories";
import logger from "Logger";

export const getOrganisations = async (event) => {
  try {
    await initRepo();
    const repo = await getOrganisationsRepo();
    const data = await repo.getOrganisations();

    // 200: Response is an array & is not empty
    if (Array.isArray(data) && data.length)
      return { statusCode: 200, body: JSON.stringify(data) };

    // 404: Response is an array and is empty
    if (Array.isArray(data) && !data.length) return { statusCode: 404 };

    return { statusCode: 400 };
  } catch (error) {
    const errorMessage = error?.message || "error fetching organisations";
    logger.error({ event: "org_get_failed" }, errorMessage);

    return { statusCode: 400, body: errorMessage };
  }
};

I want to mock the following calls using jest, as this is DB logic that I do not want to test here.

await initRepo();
const repo = await getOrganisationsRepo();
const data = await repo.getOrganisations();

And I would like to mock the return value of repo.getOrganisations();

I am not quite sure exactly how to do this. I can mock getOrganisationsRepo but then I'm not sure how to mock the return value of repo.getOrganisations()

This is pretty much as far as got with the mocks, these work, and I can test that the two functions have been called once, etc.

jest.mock("Repositories");
mockRepositories.initRepo.mockImplementation(() => Promise.resolve());
mockRepositories.getOrganisationsRepo.mockImplementation(() =>
  Promise.resolve()
);
like image 853
chinds Avatar asked Sep 18 '25 23:09

chinds


1 Answers

jest.mock() will mock the Repositories module and its functions exported will be auto mocked. This means the second mock factory function is optional. Since initRepo function is already mocked and has no resolved value, you don't need to mock it again. We should focus on mocking the getOrganisationsRepo function and its resolved/rejected value.

E.g.

getOrganisations.js:

import { initRepo, getOrganisationsRepo } from './Repositories';

export const getOrganisations = async (event) => {
  try {
    await initRepo();
    const repo = await getOrganisationsRepo();
    const data = await repo.getOrganisations();

    // 200: Response is an array & is not empty
    if (Array.isArray(data) && data.length) return { statusCode: 200, body: JSON.stringify(data) };

    // 404: Response is an array and is empty
    if (Array.isArray(data) && !data.length) return { statusCode: 404 };

    return { statusCode: 400 };
  } catch (error) {
    const errorMessage = error?.message || 'error fetching organisations';

    return { statusCode: 400, body: errorMessage };
  }
};

Repositories.js:

export async function initRepo() {
  console.log('initRepo real implementation');
}
export async function getOrganisationsRepo() {
  console.log('getOrganisationsRepo real implementation');
}

getOrganisations.test.js:

import { getOrganisations } from './getOrganisations';
import { getOrganisationsRepo } from './Repositories';

jest.mock('./Repositories');

describe('68805379', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  test('should return array data', async () => {
    const repo = {
      getOrganisations: jest.fn().mockResolvedValueOnce([{ id: 1 }]),
    };
    getOrganisationsRepo.mockResolvedValueOnce(repo);
    const actual = await getOrganisations();
    expect(actual).toEqual({ statusCode: 200, body: JSON.stringify([{ id: 1 }]) });
    expect(getOrganisationsRepo).toBeCalledTimes(1);
    expect(repo.getOrganisations).toBeCalledTimes(1);
  });
});

test result:

 PASS  examples/68805379/getOrganisations.test.js (9.919 s)
  68805379
    ✓ should return array data (5 ms)

---------------------|---------|----------|---------|---------|-------------------
File                 | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------------|---------|----------|---------|---------|-------------------
All files            |   63.16 |    21.43 |      50 |      60 |                   
 Repositories.js     |      50 |      100 |       0 |      50 | 2,5               
 getOrganisations.js |   66.67 |    21.43 |     100 |   63.64 | 13-19             
---------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.002 s

P.S. I use relative path ./Repositories instead of module alias when using jest.mock(), if you have been set up module alias, then you should use module alias as the module name for jest.mock().

like image 70
slideshowp2 Avatar answered Sep 21 '25 15:09

slideshowp2