RSpecでコントローラーの単体テストを行っていた時にエラーが発生したため、解決方法を記録として残します。
開発環境
- rails (6.0.3.3)
- rspec-rails (4.0.1)
コード内容
店舗情報の登録に関するテストを行いました。
context "管理者の場合" do
before do
@user = FactoryBot.create(:user, admin: true)
end
it "店舗情報を追加できること" do
laundry_params = FactoryBot.attributes_for(:laundry)
sign_in @user
expect {
post laundries_path, params: { laundry: laundry_params }
}.to change { Laundry.count }.by(1)
end
内容としては、
1.店舗情報を投稿するためにユーザーを生成する。
2.FactoryBot.attributes_for
でテスト用の属性値を生成してlaundry_params
に代入。
3.ログインした後に情報を送り、Laundryモデルのカウントが1上がることを確認する。
テストを実行したところ、以下のようなエラーが表示されました。
expected `Laundry.count` to have changed by 1, but was changed by 0
どうやら、データが正しく登録されていないみたいです...。
原因
画像がパラメーターに含まれていなかった。
とりあえずログを確認。
Processing by LaundriesController#create as HTML
Parameters: {"laundry"=>{"name"=>"コインランドリー名古屋店", "address"=>"愛知県名古屋市1-1", "opening_date"=>"2012-01-13", "open_time"=>"7:00", "close_time"=>"23:00", "shoe_washing"=>"true", "futon_washing"=>"true", "dryer"=>"true", "washing_machine"=>"true"}}
Rendering laundries/new.html.erb within layouts/application
パラメーターに値は含まれているがnew.html.erb
がレンダリングされている...
登録に失敗した場合new.html.erb
をレンダリングするようにしてあるため、エラーが生じていることはわかるが何が原因なのかはわからず。
「もしかしてパラメーターのキー名が間違っていてコントローラーで正しく受け取れていないのでは?」と思いストロングパラメーターを確認したところ...
def laundry_params
params.require(:laundry).permit(:name, :address, :opening_date, :open_time, :close_time, :shoe_washing, :futon_washing, :dryer, :washing_machine, :image)
end
:image(permitメソッドの最後)
・・・これだ!!!これが抜けているから画像がないぞ!とエラーになっていることが判明。
原因が判明したのはいいが、FactoryBotではデータを生成した後に画像をアタッチするようにしていたためどのようにしてパラメーターに含めればいいのかわからず苦戦しました。
FactoryBot.define do
factory :laundry do
name { 'コインランドリー名古屋店' }
address { '愛知県名古屋市1-1' }
opening_date { '2012-01-13' }
open_time { '7:00' }
close_time { '23:00' }
shoe_washing { true }
futon_washing { true }
dryer { true }
washing_machine { true }
after(:build) do |item|
item.image.attach(io: File.open('public/images/test_image.png'), filename: 'test_image.png')
end
end
end
解決方法
fixture_file_uploadメソッドを使う
fixture_file_uploadメソッドはRSpecに用意されているメソッドです。
以下の記事を参考にさせていただきました。
Active Storage 導入環境下での単体テスト
以下が、コードのbefore/afterです。
エラー発生時のテストコード
it "店舗情報を追加できること" do
laundry_params = FactoryBot.attributes_for(:laundry)
sign_in @user
expect {
post laundries_path, params: { laundry: laundry_params }
}.to change { Laundry.count }.by(1)
end
エラー解決時のテストコード
it "店舗情報を追加できること" do
#laundry_paramsにimageを追加
laundry_params = FactoryBot.attributes_for(:laundry, image: fixture_file_upload("/files/test_image.png"))
sign_in @user
expect {
post laundries_path, params: { laundry: laundry_params }
}.to change { Laundry.count }.by(1)
end
無事にテストが実行されログにもimageが含まれていました!