Отличие getBy, queryBy и findBy паттернов

React Testing Library предоставляет удобные методы для поиска элементов на странице, однако понимание различий между getBy, queryBy и findBy критически важно для написания корректных и надёжных тестов. Эти три паттерна различаются по поведению при отсутствии элементов, по синхронности и по интеграции с асинхронными сценариями.


getBy — немедленный поиск с исключением

Методы getBy* предназначены для синхронного поиска элемента и гарантируют, что элемент существует. Если элемент не найден, библиотека выбрасывает исключение. Это делает их удобными для случаев, когда элемент обязателен на момент рендеринга.

import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';

test('отображает кнопку отправки', () => {
  render(<MyComponent />);
  const button = screen.getByRole('button', { name: /отправить/i });
  expect(button).toBeInTheDocument();
});

Особенности getBy:

  • Синхронные методы: поиск происходит сразу после рендера.
  • Бросает TestingLibraryElementError, если элемент не найден.
  • Идеален для тестирования постоянных элементов, которые должны присутствовать всегда.

queryBy — безопасный поиск без исключений

Методы queryBy* также синхронные, но не бросают исключение, если элемент не найден. Вместо этого возвращают null. Это делает их полезными для проверки отсутствия элементов или элементов, которые могут быть динамически удалены.

test('не отображает сообщение об ошибке по умолчанию', () => {
  render(<MyComponent />);
  const errorMessage = screen.queryByText(/ошибка/i);
  expect(errorMessage).toBeNull();
});

Особенности queryBy:

  • Подходит для проверки отсутствия элементов.
  • Синхронные: возвращают результат сразу.
  • Не выбрасывают исключения при отсутствии элемента, что предотвращает падение теста.

findBy — асинхронный поиск с ожиданием

Методы findBy* предназначены для асинхронного поиска элементов. Они возвращают Promise, который разрешается, когда элемент появляется в DOM, либо отклоняется с ошибкой, если элемент не появляется в течение заданного таймаута (по умолчанию 1000 мс).

import userEvent from '@testing-library/user-event';

test('появляется сообщение после клика', async () => {
  render(<MyComponent />);
  const button = screen.getByRole('button', { name: /показать сообщение/i });
  await userEvent.click(button);

  const message = await screen.findByText(/сообщение отображено/i);
  expect(message).toBeInTheDocument();
});

Особенности findBy:

  • Асинхронные методы, возвращают Promise.
  • Подходит для тестирования элементов, которые появляются после действий пользователя, API-запросов или таймеров.
  • Объединяет преимущества getBy с ожиданием появления элемента.

Краткая сравнительная таблица

Паттерн Синхронность Поведение при отсутствии Использование
getBy Синхронно Ошибка Обязательные элементы
queryBy Синхронно Возврат null Проверка отсутствия или условных элементов
findBy Асинхронно Промис с ошибкой Динамически появляющиеся элементы

Рекомендации по применению

  1. Использовать getBy, когда элемент должен существовать сразу после рендера и отсутствие его является ошибкой.
  2. Использовать queryBy, чтобы проверять, что элемент не отображается в DOM или его наличие не гарантировано.
  3. Использовать findBy, когда элемент появляется асинхронно, например, после клика, задержки или запроса к серверу.

Частые ошибки

  • Попытка использовать getBy для элементов, которые появляются асинхронно. Это приведёт к неожиданным падениям теста.
  • Использование queryBy там, где требуется проверить наличие элемента. В этом случае тест может пройти даже если элемент отсутствует.
  • Игнорирование асинхронности в findBy, что часто приводит к ошибкам промиса или таймаута.

Взаимодействие с другими методами

getAllBy, queryAllBy, findAllBy расширяют поведение для множественных элементов, сохраняя логику каждого паттерна:

  • getAllBy* — синхронно, ошибка при отсутствии элементов.
  • queryAllBy* — синхронно, возвращает пустой массив при отсутствии.
  • findAllBy* — асинхронно, промис отклоняется, если элементы не появляются.

Это позволяет гибко комбинировать подходы для проверки как одного, так и множества элементов.


Понимание различий между getBy, queryBy и findBy критически важно для корректного проектирования тестов в React Testing Library. Синхронные методы обеспечивают проверку обязательных элементов и их отсутствия, а асинхронные методы позволяют безопасно работать с динамическим контентом, минимизируя ложные срабатывания и нестабильность тестов.