I have built a ReactJS application using Vite, and I am testing my application using Vitest.
I make heavy usage of react-query within my application. For mocking network requests during testing, I utilize MSW.
I am dealing with a situation where network requests which are certainly executed by code in the first test do not fail until the second test, and I am not sure how to prevent this from happening. It certainly seems to be a race condition, since requests are executed asynchronously while the application is rendered during the first test, and it seems as if some are inevitably "interrupted" when the second test begins and this consistently results in errors being logged (even though both tests pass)
describe("Test the view", () => {
beforeEach(() => {
cleanup();
server.use(...);
});
it("DEBUG Handles when rendered with a malformed uuid",
async () => {
const uuid= "fail";
consoleErrorSpy.mockImplementation(() => {
return;
});
server.use(...);
render(wrappedDetails(uuid));
await waitFor(
() => {
expect(
screen.getByText("Encountered an error while fetching")
).toBeInTheDocument();
},
{ timeout: 10000 }
);
},
{ timeout: 10000 }
);
it("DEBUG Displays the details that it is supposed to", async () => {
const uuid= faker.datatype.uuid();
render(wrappedDetails(uuid));
server.use(...);
await waitFor(() => {
expect(screen.getAllByRole("heading", { level: 3 }).length).toBe(1);
});
});
});
The wrappedDetails
that both tests render is like so:
function wrappedDetails(uuid: string) {
return (
<MemoryRouter initialEntries={["/things/" + uuid]}>
<QueryClientProvider client={queryClient}>
<GenericToastProvider>
<Routes>
<Route path="/things/:uuid" element={<ThingDetails />}></Route>
</Routes>
</GenericToastProvider>
</QueryClientProvider>
</MemoryRouter>
);
}
Unavoidably I end up with the following output:
> [email protected] qtest
> VITE_TESTING=true vitest run "-t" "DEBUG" "--no-threads"
RUN v0.29.3 /path/to/tests
stderr | src/tests/DetailsView.test.tsx > Test the Details view > Displays the details that it is supposed to
GET /api/thing/fail/task-definitions/ net::ERR_FAILED
GET /api/thing/fail/tasks/ net::ERR_FAILED
stderr | unknown test
Error: Error: connect ECONNREFUSED 127.0.0.1:3000
at Object.dispatchError (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:63:19)
at Request.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:655:18)
at Request.emit (node:events:539:35)
at ClientRequest.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:121:14)
at ClientRequest.emit (node:events:527:28)
at Socket.socketErrorListener (node:_http_client:454:9)
at Socket.emit (node:events:527:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) undefined
Error: Error: connect ECONNREFUSED 127.0.0.1:3000
at Object.dispatchError (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:63:19)
at Request.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:655:18)
at Request.emit (node:events:539:35)
at ClientRequest.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:121:14)
at ClientRequest.emit (node:events:527:28)
at Socket.socketErrorListener (node:_http_client:454:9)
at Socket.emit (node:events:527:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) undefined
✓ src/tests/thingDetailsView.test.tsx (41) 651ms
Test Files 1 passed | 9 skipped (10)
Tests 2 passed | 118 skipped (120)
Start at 16:13:28
Duration 9.43s (transform 186ms, setup 2.68s, collect 5.59s, tests 651ms)
Of particular note are the lines:
stderr | src/tests/DetailsView.test.tsx > Test the Details view > Displays the details that it is supposed to
GET /api/thing/fail/task-definitions/ net::ERR_FAILED
GET /api/thing/fail/tasks/ net::ERR_FAILED
...These are identified as happening during the second test but the second test makes no use of a uuid "fail" (that is the first test) which is what these failing requests are clearly based on, i.e. /api/thing/fail/task-definitions/
and /api/thing/fail/tasks/
and I am running out of ideas of how to make this stop.
I understand if clarification is needed in order to be able to help. I will respond quickly to any questions asked...
UPDATE 1 - 3/23/2023
A commenter asked whether I was resetting the server handlers after each test, and the answer is that yes, I am. I have the following simple setup.ts file configured:
// Polyfill "window.fetch" used in the React component.
import "whatwg-fetch";
import "@testing-library/jest-dom";
import { server } from "../mocks/server";
beforeAll(() => {
server.listen();
});
afterEach(() => {
server.resetHandlers();
});
afterAll(() => {
server.close();
});
server.listen()
in thebeforeAll
as part of a setup file, and so I think I am already following the advice from that answer. – Usually