はじめに
RSpecでテストを書く際、FactoryBotを使用してテストデータを生成することが一般的です。その際、build
と create
という2つのメソッドがよく使われますが、これらの使い分けは重要です。本記事では、これらのメソッドの違いと適切な使用場面について解説します。
build
と create
の基本的な違い
build
- メモリ上にオブジェクトを作成するが、データベースには保存しない
- 処理が高速
- データベースに影響を与えない
create
- オブジェクトを作成し、データベースに保存する
-
build
より処理が遅い - データベースに実際にレコードが作成される
使い分けの指針
buildを使用する場合
- モデルの単純なバリデーションをテストする場合
- データベースへの保存が不要なテストの場合
- テストの実行速度を重視する場合
例:
RSpec.describe User, type: :model do
let(:user) { build(:user) }
it "有効なユーザーであること" do
expect(user).to be_valid
end
it "名前がない場合は無効であること" do
user.name = nil
expect(user).to be_invalid
end
end
createを使用する場合
- データベースレベルの制約(一意性など)をテストする場合
- 関連するモデルとの相互作用をテストする場合
- データベースに保存された後の挙動をテストする場合
- type: :request のテストなど、実際のアプリケーション動作に近い環境でテストする場合
例:
RSpec.describe "Users", type: :request do
let(:user) { create(:user) }
it "ユーザー情報を取得できること" do
get user_path(user)
expect(response).to have_http_status(:success)
end
end
テストタイプ別の推奨使用方法
-
Model Spec (type: :model)
- 主に build を使用
- データベースレベルの制約をテストする場合は create を使用
-
Request Spec (type: :request)
- 主に create を使用
- 実際のHTTPリクエストをシミュレートするため、データベースにデータが存在する状態が望ましい
-
Controller Spec (type: :controller)
- 状況に応じて build と create を使い分ける
- データベースとの相互作用が必要な場合は create を使用
-
View Spec (type: :view)
- 主に build を使用
- ビューのレンダリングのみをテストする場合はデータベースへの保存は不要
まとめ
build
と create
の適切な使い分けは、テストの目的、対象となる機能、パフォーマンスの要件などを考慮することが必要だと思います。