ユーザー登録でemailを重複させないようにバリデーションをかけましが、テストのときにでFactoryBotで複数ユーザを予め生成する必要があったので方法を調べました。シーケンスを使ってユニークなデータを生成するやり方です。備忘録として残します。
問題点
ファクトリーで複数のユーザをセットアップする際に、emailをバリデーションでユニークなデータとして設定している場合、下記のようにするとテストコードが走る前に例外が発生します。
spec/factories/users.rb
FactoryBot.define do
factory :user do
user_name { "tester" }
email { "tester@example.com" }
password { "password" }
end
end
spec/models/user_spec.rb
it "複数のユーザー登録" do
user1 = FactoryBot.create(:user)
user2 = FactoryBot.create(:user)
end
これでテストを実行すると、当然ですが次のようなバリデーションエラーが発生します。
ターミナル
Failures:
1) 複数のユーザー登録
Failure/Error: user2 = FactoryBot.create(:user)
ActiveRecord::RecordInvalid:
バリデーションに失敗しました: メールアドレスはすでに存在します
解決策
シーケンスを使います。シーケンスはファクトリから新しいオブジェクトを作成するたびにカウンタの値を1づつ増やしながら値を設定します。
spec/factories/users.rb
FactoryBot.define do
factory :user do
user_name { "tester" }
sequence(:email) { |n| "tester#{n}@example.com" }
password { "password" }
end
end
email { "tester@example.com" }
をsequence(:email) { |n| "tester#{n}@example.com" }
と書き換えることで、userが生成されるたびにn
が1づつ増えていき、tester1@example.com``tester2@example.com
のようにユニークで連続したemailが設定されます。
ターミナル
#見やすいように加工してあります
user1
<User id: 13,
user_name: "tester",
email: "tester1@example.com",
password: "password",
created_at: "2020-02-05 01:56:36",
updated_at: "2020-02-05 01:56:36">
ターミナル
#見やすいように加工してあります
user2
<User id: 14,
user_name: "tester",
email: "tester2@example.com",
password: "password",
created_at: "2020-02-05 01:57:21",
updated_at: "2020-02-05 01:57:21">