14

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.

skyboyer
  • 22,209
  • 7
  • 57
  • 64

1 Answers1

21

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();
  });
});
Brian Adams
  • 43,011
  • 9
  • 113
  • 111
  • 1
    Use cycle import looks more like a hack but thank you it was very helpful for me, I was thinking to separate in different files but thing that stopped me to it that it is a bit not good solution to separate into different files one logically connected functionality. – Yaroslav Pidmohylniy Mar 16 '19 at 18:43