'How to mock a fetch function with jest ensuring to also capture the catch function?

I am trying to mock a fetch function, however this does not seem to be as simple as first thought as the code in which I am using does not seem to cover all aspects of the function.

This is the code I am trying to create a mock on:

 useEffect(() => {
    fetch('https://connectr-swapi.herokuapp.com/', {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({query: STARSHIP_QUERY})
    })
    .then(response => {response.json()})
    .then(data => setStarships(data.data.allStarships.starships))
    .catch(error => console.log({'Error': error}))
},[])

And this is what I have come up with so far but am currently receiving Error: TypeError: Cannot read property 'data' of undefined

const mockResponse = {
    data: {
        data: {
            allStarships: {
                starships: [
                    {
                        id: 1,
                        name: 'ship_1',
                        starshipClass: 'class_1',
                        maxAtmospheringSpeed: 1,
                        costInCredits: 1
                    },
                    {
                        id: 1,
                        name: 'ship_2',
                        starshipClass: 'class_2',
                        maxAtmospheringSpeed: 2,
                        costInCredits: 2
                    },
                ]
            }
        }
    }
}

beforeEach(() => {
    jest.spyOn(global, 'fetch').mockResolvedValue({
        json: jest.fn().mockResolvedValue(mockResponse)
    })
});

afterEach(() => {
    jest.resetAllMocks(); 
})

Any suggestions please?



Solution 1:[1]

Mocks are hoisted and you would not have access to the mockResponse variable unless it is included in a jest.mockImplementation

const mockFetch = jest.fn().mockImplementation(() => ({
  json: jest.fn().mockResolvedValue(mockResponse),
}));

jest.mock('node-fetch', () => {
  return jest.fn().mockImplementation((...p) => {
    return mockFetch(...p);
  });
});

The above implementation allows you to assert on mockFetch to check if it was called with variables.

I tried directly doing a mockReturn, mockResolves these didn't hoist the mockVariable along with the mock. Prefixing the variables with mock... it appears only gets hoisted along with the mocks, when you do a jest.mockImplementation and return the mock prefixed variable in the mock implementation's return statement.

Some interesting related conversations:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1