1
votes

I have a function, that is fetching data from the backend. When fetch is successful, it extracts one value from the response, and then call another function (parseAllRecordsData), that is converting the value into other value. I'm trying to test this function, but after mocking parseAllRecordsData function, it's still trying to call original function (and throws errors from that function).

In other tests jest.fn or jest.spy is working correctly, but when I'm trying to mock function that is used in "then" it's not.

export function fetchAllRecordsData(payload) {
    const url = `/apis/${payload.link.split('apis/')[1]}`;
    return axios.get(url)
        .then(({ data }) => {
            if (data && data._embedded) {
                const parsedData = data._embedded['taxonomies:entry'];
                const arrayData = parseAllRecordsData(parsedData, payload);
                return { data: List(arrayData) };
            }
            return { data: List([]) };
        })
        .catch((error) => ({ error }));
}

And my test:

describe('fetchAllRecordsData', () => {
    const mockedPayload = {
        link: 'apis/ok_link',
    };

    beforeAll(() => {
        jest.spyOn(LegalListRecordsApi,'parseAllRecordsData').mockReturnValue(['test']);
    });

    it('test', async () => {
        const test = await LegalListRecordsApi.fetchAllRecordsData(mockedPayload);
        expect(test).toEqual(1);
    });
});

When it's called like this, parseAllRecordsData calls real function, and throws the error, because mocked Axios response doesn't have some values that parsing function use. I'm only interested in return value, not calling this function.

2

2 Answers

1
votes

jest.spyOn(LegalListRecordsApi,'parseAllRecordsData').mockReturnValue(['test']); mocks the module export for parseAllRecordsData.

This doesn't have any effect on fetchAllRecordsData because it is in the same module as parseAllRecordsData and is calling it directly.

ES6 modules supports cyclic dependencies so you can import a module into itself.

Import the module into itself and use the module to call parseAllRecordsData:

import * as LegalListRecordsApi from './LegalListRecordsApi';  // import module into itself

export function fetchAllRecordsData(payload) {
  const url = `/apis/${payload.link.split('apis/')[1]}`;
  return axios.get(url)
    .then(({ data }) => {
      if (data && data._embedded) {
        const parsedData = data._embedded['taxonomies:entry'];
        const arrayData = LegalListRecordsApi.parseAllRecordsData(parsedData, payload);  // use the module
        return { data: List(arrayData) };
      }
      return { data: List([]) };
    })
    .catch((error) => ({ error }));
}

...and the call will be mocked when you mock the module export for parseAllRecordsData.

1
votes
export function fetchAllRecordsData(payload, axiosInterface = axios) {
  return return axiosInterface.get(url)
   . then(({ data }) => {
      // your code
    })
   .catch((error) => ({ error }))
}

So, you need create mock object with method get, method get should return promise.