Testing libraryでのgetBy, queryBy, findByの違いについて
getBy, queryBy, findByの違い
Testing Library には以下3種類のqueryがあります。
開発において、たびたびqueryの使い分けで混乱してしまうことがあったので、整理をこめて紹介します。
- getBy
- queryBy
- findBy
それぞれ実装例と共に説明していきます。
getBy*
指定された条件に一致する単一の要素を返します。条件に一致する要素が見つからなかった場合、または複数のマッチが見つかった場合はエラーを返されます。
同じ条件で複数の要素を確認する場合は、代わりにgetAllByを使用します。
getByは特定の条件に一致する要素を取得するために有用です。
実装例
import { render, screen } from '@testing-library/react'
test('submitボタンが表示されていること', () => {
render(<Submit />)
const button = screen.getByRole('button', { name: 'submit' })
})
queryBy*
指定された条件に一致する単一の要素を返します。条件に一致する要素が見つからなかった場合は、nullが返されます
同じ条件で複数の要素を確認する場合は、代わりにqueryAllByを使用します。(queryAllByは条件に一致する要素が見つからなかった場合、空の配列([])を返します)
queryByは特定の要素が存在しないことを確認するために有用です。
実装例
import { render, screen } from '@testing-library/react'
test('cancelボタンが表示されていないこと', () => {
render(<Submit />)
expect(screen.queryByRole('button', { name: 'cancel' }).not.toBeInTheDocument();
})
findBy*
指定された条件に一致する単一の要素を解決するPromiseを返します。条件に一致する要素が見つからなかった場合、または1000ms後に複数の要素が見つかった場合はエラーを投げます。
同じ条件で複数の要素を確認する場合は、代わりにfindAllByを使用します。
findByはgetByクエリをwaitForでラップしたクエリーです。
findByは特定の条件に一致する要素を非同期に取得するために有用です。
(非同期APIのレスポンスが帰ってきた後のコンテンツの表示や、ボタンをクリックした後のモーダル表示の確認など)
またfindByはPromiseを返すためasync/awaitかthen()を使用する必要があります。
実装例
非同期APIの呼び出し前、呼び出し後で変わる状態の確認
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import MyComponent from './MyComponent';
const server = setupServer(
rest.get('/api/data', (req, res, ctx) => {
return res(ctx.json({ data: 'dummy data' }));
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('ボタンがAPIのレスポンスを待機している間はdisableになっていること', async () => {
render(<MyComponent />);
// ボタンがdisable状態であることを確認する
const button = screen.getByRole('button', { name: 'Load Data' });
expect(button).toBeDisabled();
// ボタンをクリックする
userEvent.click(button);
// APIのレスポンスを待機する
const dataElement = await screen.findByText('dummy data');
// ボタンがenable状態になっていることを確認する
expect(button).toBeEnabled();
});
まとめ
getBy
- 特定の条件に一致する要素を取得するために有用
- 存在しない要素を取得しようとするとエラーになる
queryBy
- 特定の要素が存在しないことを確認するために有用
- 存在しない要素を取得しようとするとnullを返す
findBy
- 特定の条件に一致する要素を非同期に取得するために有用
- 存在しない要素を取得しようとするとエラーになる
- Promiseを返すためasync/awaitかthen()を使用する必要がある
ref
Discussion