はじめに
buildとcreateの違いすらよく理解せずに新規登録テストをRspecで書いて実行したところ、タイトルのようなエラーが発生しました。解決までに2時間ほどかかったので記念としてまとめておきます。なお、Railsのバージョンは5.2.6で、FactoryBotとFakerを導入しています。
背景
Rspecによくある新規登録のテストをしたかったので、まず、以下のように書きました。
spec/test_spec.rb
describe 'テスト①:ユーザー新規登録のテスト' do
let!(:user) { create(:user) }
before do
visit new_user_registration_path
fill_in 'user[name]', with: user.name
fill_in 'user[email]', with: user.email
fill_in 'user[password]', with: user.password
fill_in 'user[password_confirmation]', with: user.password_confirmation
end
context '新規登録成功のテスト' do
it '正しく新規登録される' do
expect { click_button "新規登録" }.to change { User.count }.by(1)
end
end
end
これを実行すると、以下のようなエラーが、、
Failures:
1) テスト①:ユーザー新規登録のテスト 新規登録成功のテスト 正しく新規登録される
Failure/Error: expect { click_button "新規登録" }.to change { User.count }.by(1)
expected `User.count` to have changed by 1, but was changed by 0
とりあえず、pry-byebugでデバッグすることに。テストファイルの問題の行の前にbinding.pry
を入れて実行してみました。
spec/test_spec.rb
it '正しく新規登録される' do
binding.pry
expect { click_button "新規登録" }.to change { User.count }.by(1)
end
16: context '新規登録成功のテスト' do
17: it '外部キー入力を求められることなく正しく新規登録される' do
18: binding.pry
=> 19: expect { click_button "新規登録" }.to change { User.count }.by(1)
20: end
21: end
22: end
23:
24: describe 'エラー②:フレンドリーフォワーディングの確認(新規登録・ログイン後の画面遷移先のテスト)' do
[1] pry(#<RSpec::ExampleGroups::Nested::Nested>)> User.count
=> 1
[2] pry(#<RSpec::ExampleGroups::Nested::Nested>)> User.first
=> #<User id: 1, email: "stephen@skiles-dooley.name", name: "k7hpuyja56", created_at: "2021-10-27 08:56:10", updated_at: "2021-10-27 08:56:10">
新規登録ボタンを押してないのにもうユーザーが登録されてる?なんで??賢明な諸君はもうお気づきでしょうが、結構悩みました。
解決方法
単純に、let!(:user) { create(:user) }
としていることが原因でした。create時にDBに一人のユーザーが保存されてしまい、新規登録ボタンを押す前に既にUser.count = 1
となってしまっているんですね。
正しくは、以下のようにbuildを使う必要があります。
spec/test_spec.rb
describe 'テスト①:ユーザー新規登録のテスト' do
let!(:user) { build(:user) }
before do
(以下略)
これで無事テストが通るようになりました。めでたしめでたし
最後に
初歩的なミスでしたが、buildとcreateの違いを理解する良いきっかけとなりました。基本的にcreateを使って書けば良いと思うのですが、DBに保存するような類のテストでは注意が必要だと思いました。