WHY
rspecでテストコードの記述中、Factorybotで二つの変数を定義しようとしたところ、片方は代入されるのに、片方はされなかったことが起きたのでアウトプットしていきます。
##問題
今回はテストコードを記述し、いざ実行!とするとこのようなエラー文がずらり、、、
##対処
最近エラーを解除するのがとても楽しくなってきた自分ですが、とりあえず最初に目が止まったのは
「 Failure/Error: user = FactoryBot.create(:user)」
というエラー、
まぁ調べるまでもなくuserに入っていないという意味でしょう、、しかし、コードをみてみると、
before do
item = FactoryBot.create(:item)
user = FactoryBot.create(:user)
@sample = FactoryBot.build(:sample, user_id: user.id, item_id: item.id)
end
記述は上のitemと同じ、記述は間違っていない、、、となるとFactoryBot内がおかしいのか?とおもいましたが、
UserのFactoryBotは他のspecファイルでも使用しており、そこでは問題なく動作している、、、
続いてエラー文の下の方をみてみると
「Failure/Error: _query(sql, @query_options.merge(options))」
という文字が、調べてみるとテストではたまに起きて、変数が代入しきる前にテストが実行されたりすることで起こるのだそう、、、
解決策としてはsleepというものを使う。
なので書いてみた
before do
item = FactoryBot.create(:item)
user = FactoryBot.create(:user)
@sample = FactoryBot.build(:sample, user_id: user.id, item_id: item.id)
sleep(1)
end
これでテストは1秒ごとに実行される。
しかしエラーは治らなかった、となればやっぱり代入がされない何かの理由がある!!
ということで次に目が行ったのは
「Validation failed: Email has already been taken」という文字
直訳すると「メールはすでに使われている」というもの、
deviseを使っているので一意性があるのでしっかりバリデーションが仕事してくれています!
##解決
ということでFactorybotをみにいくと、
FactoryBot.define do
factory :user do
nickname { 'Test' }
email { 'test@test' }
password { 'test111' }
password_confirmation { password }
end
end
このEmailに注目!
一意性のある値をテストするときはFakerを指定しなければならないのでemailの値を修正します!!
email { Faker::Internet.free_email }
その後テストはエラーなく無事解決しました!!
なお、「Failure/Error: _query(sql, @query_options.merge(options))」に関してはその後も出たので、
sleepはそのままにしています。