Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest mock function inside function

I have no idea how to mock return value of inner function inside jest I tried different approaches. Finally I found this answer but value not mocking for some reason, here it is example:

countries.js

export const countryList = () => [
      {
        label: '+244',
        value: 'Angola',
      }, // list of all possible countries very long...
 ];

export const getSortedCountryData = intlLang =>
  countriesList()
  .sort((compare, comparable) =>
    compare.value.localeCompare(comparable.value, intlLang, { sensitivity: 'base' }));

countries.test.js

import * as countyListHelper from './countries';

describe('countries list', () => {
  test('returns list of countries', () => {
    const mockFn = jest.mock();

    const expectedList = [
      {
        label: '+244',
        value: 'Angola',
      },
      {
        label: '+43',
        value: 'Austria',
      },
    ];

    mockFn.spyOn(countyListHelper, 'countriesList').mockReturnValue(expectedList);

    // console.log('if return value mocked correctly',
    // countyListHelper.countriesList() === expectedList); // true
    expect(countyListHelper.getSortedCountryData('en')).toEqual(expectedList);
    // shows error with received value list of all countries instead of mocked one
  });
});

Please suggest me any possible solutions why inside test function mocked return value for inner function is ignored. Setup from Create React App.

like image 653
Yaroslav Pidmohylniy Avatar asked Mar 15 '19 16:03

Yaroslav Pidmohylniy


People also ask

How do you mock a function inside a function?

You can mock functions in two ways: either you create a mock function to use in test code, or you write a manual mock that overrides a module dependency. Let's take for example the case where we're testing an implementation of a function forEach, which will invoke a callback for each item in a supplied array.

How do you call a function inside a function in Jest?

You can create a namespace that you export as the default object and call b using the namespace. This way, when you call jest. mock it will replace the b function on the namespace object. const f = require('./f'); jest.

Can I use Jest mock inside a test?

mock() doesn't work inside tests, only outside tests.


1 Answers

The question you linked to has a currently accepted answer that doesn't work. I added a new answer with an explanation and working example.

The same concept applies here: a mock replaces the module export of a function so to be able to mock countriesList within getSortedCountryData you have to call the module export for countriesList.

One option is to move countriesList to its own module.

The other option is to take advantage of the fact that "ES6 modules support cyclic dependencies automatically" so it is perfectly valid to import the module into itself so that you can call the module export for countriesList:

countries.js

import * as countyListHelper from './countries';

export const countriesList = () => [
  {
    label: '+244',
    value: 'Angola',
  }, // list of all possible countries very long...
];

export const getSortedCountryData = intlLang =>
  countyListHelper.countriesList()
    .sort((compare, comparable) =>
      compare.value.localeCompare(comparable.value, intlLang, { sensitivity: 'base' }));

countries.test.js

import * as countyListHelper from './countries';

describe('countries list', () => {
  test('returns list of countries', () => {

    const expectedList = [
      {
        label: '+244',
        value: 'Angola',
      },
      {
        label: '+43',
        value: 'Austria',
      },
    ];

    const spy = jest.spyOn(countyListHelper, 'countriesList');
    spy.mockReturnValue(expectedList);

    expect(countyListHelper.getSortedCountryData('en')).toEqual(expectedList);  // Success!

    spy.mockRestore();
  });
});
like image 187
Brian Adams Avatar answered Sep 27 '22 20:09

Brian Adams