From toBeNull()
to not.toBeInTheDocument()
: Writing Meaningful Tests in React
When talking about react-testing-library, we need to make sure we have a user-centric approach at all times.
When testing for the absence of elements, developers often find themselves choosing between assertions like toBeNull()
, toHaveLength(0)
, and not.toBeInTheDocument()
. While these assertions might seem interchangeable at first glance, they each have specific use cases and nuances that can impact the clarity and performance of your tests.
But what is the difference between them? Which should we use to keep best practices when following the user-centric approach?
toBeNull()
The standard getBy
methods throw an error when they can't find an element, so if you want to make an assertion that an element is not present in the DOM, you can use queryBy
APIs instead:
const submitButton = screen.queryByText('submit')
expect(submitButton).toBeNull() // it doesn't exist
- Performance: Efficient, as it directly checks the returned value from the query method.
- Screening: Does not screen the entire DOM; only checks the specific query result.
- Timing: Fast, as it’s just a simple comparison.
toHaveLength(0)
The queryAll
APIs version return an array of matching nodes. The length of the array can be useful for assertions after elements are added or removed from the DOM.
const submitButtons = screen.queryAllByText('submit')
expect(submitButtons).toHaveLength(0) // expect no elements
- Performance: Slightly more overhead than
toBeNull()
as it involves array length check, but still efficient. - Screening: Checks the result of an array-based query, not the entire DOM.
- Timing: Fast, though it involves an array operation.
⭐️ not.toBeInTheDocument()
The jest-dom
utility library provides the .toBeInTheDocument()
matcher, which can be used to assert whether an element is in the body of the document or not. This can be more meaningful than asserting a query result is null
. Useful for readability and clarity in certain contexts.
import '@testing-library/jest-dom'
// use `queryBy` to avoid throwing an error with `getBy`
const submitButton = screen.queryByText('submit')
expect(submitButton).not.toBeInTheDocument()
- Performance: Generally efficient, but involves an additional step to verify the node is not in the document.
- Screening: Ensures the element is not part of the current document, but it might involve slightly more processing to verify the node’s presence.
- Timing: Even though,
not.toBeInTheDocument()
will screen the entire DOM; it seems irrelevant in terms of timing.

Best Practice for User-Centric, Meaningful Assertions
For a user-centric approach, not.toBeInTheDocument()
is often the most meaningful assertion:
- Explicitness: It clearly states that the element should not be present in the document, aligning well with user expectations.
- Readability: It makes tests more readable and understandable for other developers, as it conveys a clear and explicit intent.
Final Recommendation
While all three assertions are useful, not.toBeInTheDocument()
is generally recommended for the most explicit, user-centric, and meaningful assertion of an element's absence in the document. This choice aligns well with best practices in testing, providing clear, readable, and user-focused tests.