I am using axios-mock-adapter to test my components. The strange thing is that only a single test can be run successfully because the next one always breaks. Each test works fine if run individually.
Here is my setup.
"axios-mock-adapter": "^1.21.1",
"axios": "^0.27.2",
"@testing-library/jest-dom": "^5.16.1",
"react": "^17.0.2",
"typescript": "^4.5.4",
util.ts
export const client = axios.create({
baseURL: process.env.REACT_APP_API_URL ? process.env.REACT_APP_API_URL : "",
timeout: 10000,
});
The exported client is used internally by all my components
component.test.tsx
import MockAdapter from "axios-mock-adapter";
import {apiUrls, client} from "utils";
import {DUMMY_RESPONSE} from "dummy/data";
import {render, screen, waitFor} from "@testing-library/react";
import {MemoryRouter} from "react-router-dom";
import MyComponent from "MyComponent";
describe('MyComponent', () => {
let mockClient: MockAdapter;
beforeAll(() => {
mockClient = new MockAdapter(client);
})
afterEach(() => {
mockClient.reset()
})
afterAll(()=>{
mockClient.restore()
})
it('should fetch images and render them', async () => {
mockClient.onGet(apiUrls.myURL).reply(200, DUMMY_RESPONSE)
const spy = jest.spyOn(client, 'get')
render(
<MemoryRouter>
<MyComponent handleSubmit={() => {
}}/>
</MemoryRouter>)
await waitFor(() => expect(spy).toBeCalledWith(apiUrls.fetchSecurityImages))
await waitFor(() => expect(spy).toBeCalledTimes(1))
await waitFor(() => {
DUMMY_RESPONSE.forEach((image) => {
expect(screen.getByAltText(image.alt)).toBeDefined()
})
})
spy.mockClear()
});
it('should show loader while fetching images', async () => {
mockClient.onGet(apiUrls.myURL).reply(200, DUMMY_RESPONSE)
const spy = jest.spyOn(client, 'get')
render(
<MemoryRouter>
<MyComponent handleSubmit={() => {
}}/>
</MemoryRouter>)
await waitFor(() => expect(spy).toBeCalledWith(apiUrls.myURL))
await waitFor(() => expect(spy).toBeCalledTimes(1))
await waitFor(() => {
DUMMY_RESPONSE.forEach((image) => {
expect(screen.getByAltText(image.alt)).toBeDefined()
})
})
spy.mockClear()
});
});
The second test (I mean the second that is run not the order they are defined) always breaks because of an error in the useEffect() hook which throws:
Cannot read properties of undefined (reading 'data')
TypeError: Cannot read properties of undefined (reading 'data')
And this is the function that breaks:
useEffect(() => {
const fetchImages = async () => {
try {
const response = await client.get(apiUrls.fetchImages) // <--- here we get undefined
setImages(response.data)
} catch (e: any) {
handleErrors(e)
}
}
fetchImages()
}, [])
BTW I am aware those tests look the same. That is exactly the point. Earlier there was a delay introduced in the second one but while debugging I changed them to pinpoint the problem but with no luck.