Search code examples
axiosreact-testing-libraryts-jestreact-typescriptjest-mock-axios

Mocking an api call in Jest with React Typescript


I'm following some documentation on mocking an api call with Jest, although trying to do it with react.tsx. I've looked at a lot of different stack Q&As and elsewhere online and am not understanding what I am missing from my test file to make my test pass. So far I'm exporting my fetchWeatherData function from my WeatherMocks.tsx:

import axios from 'axios';
    
export const fetchWeatherData = async () => {
  const response = await axios.get('http://mock-api-call/weather/get-weather');
  return response.data.result.weather.forcast;
};

and importing to my test file where I am trying to use this function to mock the data. Weather.test.tsx:

import axios from 'axios';
import { fetchWeatherData } from '../../__mocks__/WeatherMocks';
    
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
    
describe('mock api calls', () => {
  afterEach(() => {
    jest.resetAllMocks();
  });
    
  test('return forcast Sunny', async () => {
    mockedAxios.get.mockResolvedValue({
       data: {
         result: {
           weather: {
            forcast: 'Sunny',
            max: 28,
            min: 17,
            description: 'Clear skys all day with a warm summber breaze ariving in the afternoon',
          },
        },
      },
    });

    const forecast = await fetchWeatherData();
    expect(forecast.forcast).toEqual('Sunny');
  });
});

If someone can help me get past this hurdle I would greatly appreciate it as I was told this is a really simple method.

The new testing error

 expect(received).toEqual(expected) // deep equality
    
    Expected: "Sunny"
    Received: undefined
    
      24 |     });
      25 |     const forecast = await fetchWeatherData();
    > 26 |     expect(forecast.forcast).toEqual('Sunny');
         |                              ^
      27 |   });
      28 | });
      29 |

Solution

  • Second answer

    It is failing because in your method you are already returning the weather:

      // ...
      const forecast = await fetchWeatherData();
      const expect(forecast).toEqual('Sunny');
      // ...
    

    Previous answer

    What you are doing is already correct, however you are not creating the object structure which you are later accessing:

    import axios from 'axios';
    import { fetchWeatherData } from '../../__mocks__/WeatherMocks';
    
    jest.mock('axios');
    const mockedAxios = axios as jest.Mocked<typeof axios>;
    
    describe('mock api calls', () => {
      afterEach(() => {
        jest.resetAllMocks();
      });
    
      test('return forcast Sunny', async () => {
        mockedAxios.get.mockResolvedValue({
          // You need to mock all the structure:
          // response -> data -> result -> weather -> forcast
          // You have only:
          // response -> data
          data: {
            result: {
              weather: {
                // Are you sure its forcast and not forecast??
                forcast: 'Sunny',
                max: 28,
                min: 17,
                description: 'Clear skys all day with a warm summber breaze ariving in the afternoon',
              },
            },
          },
        });
    
        const forecast = await fetchWeatherData();
        expect(forecast).toEqual('Sunny');
      });
    });