React Testing Libraryには、DOM要素を取得するためのさまざまなメソッドがあります。
その中でも、getBy
、queryBy
、findBy
はDOM要素を取得する際に頻繁に使用されますが、これらのメソッドの使い分けに迷うことがあるかもしれません。
この記事では、それぞれのメソッドの「違い」や「使い分け」をシンプルなサンプルコードとともに解説します。
getBy, queryBy, findByの違い
まず最初にgetBy
、queryBy
、findBy
の「違い」と「使い分け」を以下にまとめます。
getBy | queryBy | findBy | |
特徴 | ・指定した条件に一致する要素を返す | ・指定した条件に一致する要素を返す ・条件に一致する要素が見つからない場合には null を返す | ・指定した条件に一致する要素をPromise で返すメソッド |
エラーの 発生条件 | ・条件に一致する要素が見つからなかった場合 ・条件に一致する要素が複数ある場合 | ・条件に一致する要素が複数ある場合 | ・条件に一致する要素が指定時間内(デフォルト1000ms)に見つからない場合 ・条件に一致する要素が複数ある場合 |
使い分け | 条件に一致する要素を取得する時に使用する | 条件に一致する要素が存在しないことを確認する時に使用する | 条件に一致する要素が非同期にDOMに追加される場合に使用する |
ではこれから、以下のサンプルコードに示しているMyComponent
のテストをgetBy
、queryBy
、findBy
を用いて行ってみましょう。
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [showLoadMore, setShowLoadMore] = useState(false);
// 500ms後に「Load More」ボタンを表示
useEffect(() => {
const timer = setTimeout(() => {
setShowLoadMore(true);
}, 500);
return () => clearTimeout(timer);
}, []);
return (
<div>
<button>Submit</button>
{/* 500ms後に表示される「Load More」ボタン */}
{showLoadMore && <button>Load More</button>}
</div>
);
}
export default MyComponent;
getByの使い方
getBy
は、指定した条件に一致する要素を返すメソッドです。条件に一致する要素が見つからなかった場合や、条件に一致する要素が複数ある場合にはエラーが発生します。条件に一致する要素が1つだけであることが前提の場合に使用しましょう。複数の要素が存在する場合には、getAllBy
メソッドを使用します。
getBy
を用いたサンプルコードを以下に示します。
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import MyComponent from './MyComponent';
test('Submitボタンが表示されているか', () => {
render(<MyComponent />);
const submitButton = screen.getByRole('button', { name: 'Submit' });
expect(submitButton).toBeInTheDocument();
});
上記のサンプルコードでは、getByRole
を使用して「Submit」ボタンが画面に表示されているかを確認しています。今回は、"Submit" というラベルを持つボタンが1つだけ存在するため、テストが成功しています。
queryByの使い方
queryBy
は、getBy
と同様に指定した条件に一致する要素を返しますが、要素が見つからなかった場合にはエラーではなくnull
を返す点が異なります。そのため、queryBy
は条件に一致する要素が存在しないことを確認する時に使用します。また、条件に一致する要素が複数ある場合には、queryAllBy
メソッドを使用します。
queryBy
を用いたサンプルコードを以下に示します。
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import MyComponent from './MyComponent';
test('Load Moreボタンが初期状態では表示されていないか', () => {
render(<MyComponent />);
const loadMoreButton = screen.queryByRole('button', { name: 'Load More' });
expect(loadMoreButton).toBeNull();
});
上記のサンプルコードでは、queryByRole
を使用して、「Load More」ボタンが初期状態では表示されていないことを確認しています。queryBy
は、条件に一致する要素が見つからなかった場合にnull
を返すため、expect(loadMoreButton).toBeNull()
でボタンが表示されていないことを確認できます。
findByの使い方
findBy
は、指定された条件に一致する要素が非同期でDOMに追加される場合に使用するメソッドです。このメソッドはPromise
を返すため、async/await
やthen()
を使用して、要素が見つかるまで待つ処理が必要になります。条件に一致する要素が指定時間内(デフォルト1000ms)に見つからない場合や条件に一致する要素が複数ある場合にはエラーが発生します。また、条件に一致する要素が複数ある場合には、findAllBy
メソッドを用います。
findBy
を用いたサンプルコードを以下に示します。
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import MyComponent from './MyComponent';
test('Load Moreボタンが0.5秒後には表示されているか', async () => {
render(<MyComponent />);
const loadMoreButton = await screen.findByRole('button', { name: 'Load More' });
expect(loadMoreButton).toBeInTheDocument();
});
上記のサンプルコードでは、findByRole
を使用して、500ms後にDOMに追加される「Load More」ボタンが正しく表示されているかを確認しています。await
を使って指定された時間内にボタンが表示されるのを待機し、expect(loadMoreButton).toBeInTheDocument()
でボタンが画面に正しく表示されているかを確認しています。
本記事のまとめ
この記事ではReact Testing LibraryのgetBy
、queryBy
、findBy
メソッドについて、以下の内容を説明しました。
getBy
- 要素が必ず存在する場合に使用し、要素が見つからなかった場合にはエラーが発生します。
queryBy
- 要素が存在しないことを確認したい場合に使用し、見つからなければ
null
を返します。
- 要素が存在しないことを確認したい場合に使用し、見つからなければ
findBy
- 非同期にDOMに追加される要素を取得する場合に使用し、
Promise
を返します。
- 非同期にDOMに追加される要素を取得する場合に使用し、
お読み頂きありがとうございました。