【Rails】RSpecテストでActiveRecord::RecordInvalid:Validation failed: Email has already been taken エラー
環境
テスト後にロールバックしていない
該当のRSpec
require 'rails_helper' describe 'レコード管理機能', type: :system do describe '一覧表示機能' do before do user_a = FactoryBot.create(:user, name: 'ユーザーA', email:'a@example.com') FactoryBot.create(:record, weight: 74.2, user: user_a) end 〜 中略 〜 end end
テストの実行前にbefore do
でuser_aを作成しています。
このテストを実行し、1回目は上手くいきましたが、まったく同じままもう一度テストするとエラーが出てしまいました。
# 同じテストの2回目で $ docker-compose run web rspec => ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
Validation failed: Email has already been taken
というエラー文そのままです。つまり、メールアドレスがすでに登録されててバリデーションエラーになっとるよということです。
ということは、1回目のテスト実行の時に作成したユーザーデータが残ってしまっているということになります。
rails_helper.rbを確認しよう
エラー文をそのままググると、「database_cleanerっていうgemを入れよう!」という解決策が一番に目につきますが、それよりもまず確認してほしいのは、RSpecをインストールした際に自動生成しているrails_helper.rbです。
RSpec.configure do |config| config.use_transactional_fixtures = true # ↑この一文が抜けていた 〜 中略 〜 end
このconfig.use_transactional_fixtures = true
という1文がテストの終わりにdbをロールバックするものになります。あぁ、これが抜けてたのかー、書き足せば大丈夫だな!っと思いきや
テスト環境のDBをリセットしよう
ロールバックという操作はあくまで、一連のトランザクションの取り消しでしかありませんから、すでに登録されているデータまでをクリアしてくれる訳ではありません。
なので途中からconfig.use_transactional_fixtures = true
を書き足したとて
# rails_helper.rb修正後 $ docker-compose run web rspec => ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
バリデーションエラーはそのまま残ることになります。 なので一旦、DBのリセットを行いました。
$ docker-compose run web bundle exec rake db:migrate:reset RAILS_ENV=test => Starting weinance_chrome_1 ... done Starting weinance_db_1 ... done Dropped database 'app_name_test' Created database 'app_name_test' == 20190818090640 CreateRecords: migrating ==================================== -- create_table(:records) (以下略)
RAILS_ENV=test
を忘れないでください。
そして再度チャレンジ
# 1回目 $ docker-compose run web rspec => Starting weinance_db_1 ... done Starting weinance_chrome_1 ... done 〜 中略 〜 Finished in 4.89 seconds (files took 8.88 seconds to load) 1 example, 0 failures # 2回目 $ docker-compose run web rspec => Starting weinance_db_1 ... done Starting weinance_chrome_1 ... done 〜 中略 〜 Finished in 4.26 seconds (files took 7.33 seconds to load) 1 example, 0 failures
2回目も問題なくテストが通りました。