dmikester1
dmikester1

Reputation: 1370

Mocking an axios post using React Testing Library / Jest

I am struggling with figuring out how to correctly mock this Axios post in my React test. It seems like the documentation and tutorials out there are all over the place in terms of how they do it, no strong consensus or best practice.

So here is my Test: BatchList.test.js

import React from 'react';
import { setupWorker, rest } from 'msw';
import {
    render,
    screen,
    within,
    fireEvent,
    waitFor,
} from '@testing-library/react';
import '@testing-library/jest-dom';
import { Provider as AlertProvider } from 'react-alert';
import AlertMUITemplate from 'react-alert-template-mui';
import BatchList from './BatchList';
import mockedAxios from 'axios';

// ... other tests that succeed here ...

// only test that fails here
test('clicking yes and passing back only 2 valid batch numbers should show 2 valid, 2 invalid batch numbers in list', async () => {
    // renderBatchListWithNumbers();
    const batchList = render(
        <AlertProvider template={AlertMUITemplate}>
            <BatchList
                formulaID={''}
                orderID={''}
                itemID={''}
                formulaResults={[]}
                batchNumbers={[
                    { BATCH_ID: '987654', ID: '78' },
                    { BATCH_ID: '261010', ID: '79' },
                    { BATCH_ID: '301967', ID: '80' },
                    { BATCH_ID: '445566', ID: '81' },
                ]}
                setBatchNumbers={mockedEmptyFn}
                batchNumber={'5'}
                setBatchNumber={mockedEmptyFn}
            />
        </AlertProvider>
    );
    const completeButton = batchList.getByText('Complete');
    fireEvent.click(completeButton);
    const yesButton = batchList.getByText('Yes');
    expect(yesButton).toBeInTheDocument();
    fireEvent.click(yesButton);

    // now we need to figure out mocking the API calls!!!
    const data = {
        msg: 'fail',
        invalidBatchNumbers: ['987654', '445566'],
    };
    mockedAxios.post.mockResolvedValueOnce({
        data: data,
    });

    await waitFor(() => {

        expect(batchList.getByText('987654')).toHaveClass('invalid');
        expect(batchList.getByText('261010')).toHaveClass('valid');
    });
});

And here is my axios.js inside my __mocks__ folder:

export default {
    post: jest.fn().mockResolvedValue(),
};

So the error I am getting in my test is this: thrown: "Unable to complete all batches - TypeError: (0 , _axios.default) is not a function"

And that error message string is coming from my client side API call here:

export const completeAllBatches = async (
    orderID,
    itemID,
    batchNumbers
) => {
    const completeAllBatchesURL =
        serverURL + `:${port}/completeAllBatches`;

    try {
        return await axios({
            method: 'post',
            url: completeAllBatchesURL,
            timeout: shortTimeout,
            data: {
                orderID,
                itemID,
                batchNumbers,
            },
        })
            .then((res) => {
                return res;
            })
            .catch((e) => {
                return Promise.reject(
                    '1: Unable to complete all batches - ' + e
                );
            });
    } catch (e) {
        return Promise.reject('2: Unable to complete all batches - ' + e);
    }
};

Upvotes: 2

Views: 26886

Answers (1)

Jonathon H.
Jonathon H.

Reputation: 326

I solved a similar problem, perhaps this is useful?

Why this break?

  • I think the problem is that typescript doesn't know how to handle some of the complexities of an axios.post.

Instead of importing default as mocked, I imported as normal

import axios from 'axios'
jest.mock('axios');

Then I am a bit more explicit with the mock

const mockedAxios = axios as jest.Mocked<typeof axios>;
let payload:object = {}
const mockedPost = mockedAxios.post.mockReturnValueOnce(payload);
//I highly recommend separating out api client like in the tutorial, then call that api function...
const data = await postBatch();
expect(axios.post).toHaveBeenCalled();

LMK if this works for you, I'm still playing with my React testing patterns :)

Upvotes: 3

Related Questions