Did you forget to wait something async in your test?

November 20, 2021 • 2 min read

Attempted to log “TypeError: Cannot read properties of null (reading ‘URL’)

It’s one of those dreaded, time consuming flaky errors that everyone working with Jest has had to deal with.

The first part of the error is quite clear. Apparently there was still something going on after my test has finished. But what? Problem with this particular error was that it didn’t happen every time (so timing issue?) and it was generally logged after all my tests had run. So, no clue which test was causing it.

The full stacktrace was:

    Attempted to log "TypeError: Cannot read properties of null (reading 'URL')
        at Object.exports.setup (src/node_modules/jsdom/lib/jsdom/living/generated/XMLHttpRequest.js:62:12)
        at new XMLHttpRequest (src/node_modules/jsdom/lib/jsdom/living/generated/XMLHttpRequest.js:101:22)
        at dispatchXhrRequest (src/node_modules/axios/lib/adapters/xhr.js:44:19)
        at new Promise (<anonymous>)
        at xhrAdapter (src/node_modules/axios/lib/adapters/xhr.js:24:10)
        at dispatchRequest (src/node_modules/axios/lib/core/dispatchRequest.js:46:10)
        at Object.defaultQueryFn [as queryFn] (src/src/providers/queryClient.ts:19:7)".

As often with these errors the cause was pretty simple and the solution even simpler.

I’m using React-Query for my api requests, which is a fantastic tool that offers so many functionalities out of the box. One of its features is the prefetching data you know a user is gonna need.

And that’s what I recently added. After the page had fully loaded the frontend starts prefetching some of the other options in a dropdown, so that when the user selects one of the other options the results are there instantly!

Problem was that in some tests these prefetching calls where still running after the test has finished.

In my setupTests.ts file I have the following call to start with a new React Query slate for every test:

afterEach(() => {
  queryClient.clear()
})

Which is great if you want test isolation, but in this case it was causing errors, because the prefetching calls where still running when the query client got cleared.

The solution to this problem is simple and effective:

afterEach(async () => {
	await queryClient.cancelQueries();	queryClient.clear();
});

After every test this will first cancel any queries that are still running and then clear the queryClient.

Problem solved!

Got any questions, found a mistake? You can find me on Twitter as @vnglst. You can also discuss the article on TwitterSuggest changes on Gitlab


Koen van Gilst

Koen van Gilst

Personal blog by Koen van Gilst. JavaScript developer, M.A. in Philosophy, former translator.