ctimmerm / axios-mock-adapter

Axios adapter that allows to easily mock requests
MIT License
3.42k stars 241 forks source link

onGet reusing wrong reply #347

Open macskay opened 1 year ago

macskay commented 1 year ago

I have multiple tests in one file, one is to check whether the state is changed correctly if the response returns 200. The other should check if a 401 is handled correctly. When I run them separately, meaning I comment one of the two out the work fine. However when running them side-by-side the second one returns the reply from the first one.

Here is my file

describe('HouseList', () => {
    let store;
    let mock;
    let wrapper;

    beforeEach(() => {
        mock = new MockAdapter(axios);
        store = createStore();
    });

    afterEach(() => {
        mock.reset();
    });

    test('Renders', () => {
        mock.onGet(`${BACKEND_URL}/user/users?size=100`).reply(200, {});
        let wrapper = mount(HouseList, {
            store,
            vuetify
        });
        expect(wrapper.find('.content').exists()).toBeTruthy();
    });

    test('Users are Loaded on Mount', async () => {
        const response = {
            content: [
                {id: 1, firstname: 'The', lastname: 'Hulk', status: 'ACTIVE'}]}}
            ]
        }
        mock.onGet(`${BACKEND_URL}/user/users?size=100`).reply(200, response);
        mount(HouseList, {
            store,
            vuetify
        });

        await flushPromises(); // Waiting for Axios async

        expect(mock.history.get[0].url).toEqual(`${BACKEND_URL}/user/users?size=100`);
        expect(store.state.view.userList.loaded).toBeTruthy();
        expect(store.state.view.userList.users.length).eq(1);
        expect(store.state.view.userList.users[0].lastname).equals('Hulk');
    });

    test('Opens Error Message, when Receiving Error on User Load', async () => {
        mock.onGet(`${BACKEND_URL}/user/users?size=100`).reply(401, {});
        let wrapper = mount(HouseList, {
            store,
            vuetify
        });

        async flushPromises();

        expect(store.state.error.show).toBeTruthy();
        expect(wrapper.find("v-dialog")).toBeTruthy();
    });
});
❯ test/components/Characters/HouseList.test.js (3) 437ms
   ❯ HouseList (3) 436ms
     ✓ Renders 302ms
     ✓ Users are Loaded on Mount
     × Opens Error Message, when Receiving Error on User Load

When inspecting mock.history the history of the second test is empty, where as for the first one the get shows. Am I missing sth here?

One addition: The axios call I'm stubbing is called on beforeMount in my Vue Component, which is why I mount it after setting up the mock instead of setting the wrapper in beforeEach of the test file.

jazimabbas commented 1 year ago

Yes, you are right. Got the same error.

jazimabbas commented 1 year ago

@macskay I go through the source code. What I found is if we create new axios instance every time, then it will work. This is not the problem with onGet. This problem come up in every HTTP methods if we use the same url.

rev42 commented 2 months ago

Hello @marcbachmann @ctimmerm Do you know if it is a feature or a bug?

If mock.reset(); is triggered in the afterEach, it should resets the handlers between each test meaning that it should wipe all mocks for all mocked routes, shouldn't it?

anthony-bernardo commented 1 month ago

I get the same bug

import '@testing-library/jest-dom'
import { cleanup, render, screen, waitFor } from '@testing-library/react'
import MockAdapter from 'axios-mock-adapter'
import axiosInstance from 'app/utils/AxiosInstance'
import StockDetailPage from '../page'

jest.mock('next/navigation', () => ({
    useRouter: () => ({
        push: jest.fn(),
        back: jest.fn(),
    }),
}))

describe('EditStockPage', () => {
    let mock: any

    beforeEach(() => {
        mock = new MockAdapter(axiosInstance)
    })

    afterEach(() => {
        mock.reset()
    })

    it('displays by default the `CHF/Unité` or `CHF/kg-ltr` according to the api response', async () => {
        mock.onGet('/api/stock/1020').reply(200, {
            packagings: [expect.any(Object)],
            priceByPackaging: true,
            unit: expect.any(String),
        })

        render(<StockDetailPage params={{ id: '1020' }} />)

        await waitFor(() => {
            expect(screen.getByText('CHF/unité')).toBeInTheDocument()
            mock.reset()
        })
    })

    it('fooo', async () => {
        mock.onGet('/api/stock/1020').reply(200, {
            packagings: [expect.any(Object)],
            priceByPackaging: false,
            unit: 'KILOGRAM',
        })

        render(<StockDetailPage params={{ id: '1020' }} />)

        await waitFor(() => {
            expect(screen.getByText('CHF/kg')).toBeInTheDocument()
        })
    })
})