LoginSignup
2
1

More than 3 years have passed since last update.

コントローラーのテスト時に画像をアップロードする方法

Posted at

RSpecでコントローラーの単体テストを行っていた時にエラーが発生したため、解決方法を記録として残します。

開発環境

  • rails (6.0.3.3)
  • rspec-rails (4.0.1)

コード内容

店舗情報の登録に関するテストを行いました。

laundries.spec.rb

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

どうやら、データが正しく登録されていないみたいです...。

原因

画像がパラメーターに含まれていなかった。

とりあえずログを確認。

test.log
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をレンダリングするようにしてあるため、エラーが生じていることはわかるが何が原因なのかはわからず。
「もしかしてパラメーターのキー名が間違っていてコントローラーで正しく受け取れていないのでは?」と思いストロングパラメーターを確認したところ...

contoroller.rb
  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ではデータを生成した後に画像をアタッチするようにしていたためどのようにしてパラメーターに含めればいいのかわからず苦戦しました。

FabtoryBot
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が含まれていました!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1