Search code examples
reactjsreact-testing-libraryjest-dom

Reasons to use getBy* in conjunction with toBeInTheDocument


There are plenty of examples of getBy* or findBy* queries are used in conjunction with expect().toBeInTheDocument(). At the same time the Testing Library docs say that both of those type of queries throw errors when 0 elements match.

So there is a situation that when we do expect(screen.getByText('some text')).toBeInTheDocument() we're checking the element presence twice, which is redundant.

What's the reason everyone's doing this?


Solution

  • It's purely for readability. You don't really need the assertion .toBeInTheDocument(), or any other. As you say, in the failing case the error that fails the test is actually thrown by the getBy* method - expect is never even called.

    However, using the expect(actual).matcher(expected) form makes it clearer that you're asserting on the presence of the element, whereas having getBy* on its own isn't very explicit. Readers will expect a test to have a certain "ryhthm", where some preconditions are set up (Arrange or Given), some action is taken (Act or When), and some postconditions are checked (Assert or Then). If a test ends without any expectations, that can look like a mistake.

    You may also have lint rules (like jest/expect-expect, although that can be configured to include getBy* as expectations) or Jest's own expect.hasAssertions() that will be unhappy if you leave the assertion to be implicit, even in the passing case.

    Testing Library has its own ESLint rules, which includes testing-library/prefer-explicit-assert covering this behaviour too; that says (emphasis mine):

    This rule aims to encourage users to explicitly assert existence of elements in their tests rather than just use getBy* queries and expect it doesn't throw an error so it's easier to understand what's the expected behavior within the test.