简体   繁体   English

使用 React 测试库/Jest 模拟 axios 帖子

[英]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.我正在努力弄清楚如何在我的 React 测试中正确地模拟这个 Axios 帖子。 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所以这是我的测试: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:这里是我的axios.js里面我__mocks__文件夹:

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"所以我在测试中遇到的错误是: 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:该错误消息字符串来自我的客户端 API 调用:

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);
    }
};

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.我认为问题在于打字稿不知道如何处理 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 data:object = {}
const mockedPost = mockedAxios.post.mockReturnValueOnce(data);
//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 :) LMK 如果这对你有用,我还在玩我的 React 测试模式:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM