遭遇した現象
ActiveStorageを使っているプロジェクトで、fixture_file_upload
を含むテストを追加したら、
関係ないはずの他のテストがランダムに失敗するようになった。
追加したのはこんな感じのテスト。
test "create with valid file attachment" do
image_file = fixture_file_upload("test/fixtures/files/sample.jpg", "image/jpg", :binary)
post somethings_path, params: { something: { name: "新規作成",
image: image_file } }
assert_response :created
end
失敗時のエラー
NoMethodError: undefined method `column_types' for nil:NilClass
- 常にではない。成功するときもある。
fixture_file_upload
を含むテストをコメントアウトすると、常に成功するようになる。
コメントアウトを戻すとまたランダムに失敗する。- ActiveStorageの代わりにCarrierWaveを使っているプロジェクトでは、発生したことがない。(Railsのバージョンは同じ)
content_type
をチェックするようなバリデーションがあるので、そこで失敗していそう。
解決策
下記Railsガイドを参考に、アップロードしたファイルをクリーンアップする処理を追加。
Active Storage の概要 - 11 結合テスト中に保存したファイルを破棄する
remove_uploaded_files.rb
というファイルを作って、
# コードはRailsガイドより引用
module RemoveUploadedFiles
def after_teardown
super
remove_uploaded_files
end
private
def remove_uploaded_files
FileUtils.rm_rf(Rails.root.join('tmp', 'storage'))
end
end
module ActionDispatch
class IntegrationTest
prepend RemoveUploadedFiles
end
end
テストのファイルで require
require "test_helper"
require "remove_uploaded_files" # この行を追加
そうすると、発生しなくなった。
何が行われている?
追加したコードにより、テストの実行後に、 tmp/storage
ディレクトリが削除されている。
Railsガイドの解説にある以下のエラーが発生していたのではと思われる。
このコールバックを実行すると、テスト中に作成されたすべての接続を確実に完了するので、Active Storageでファイルが見つからないというエラーは表示されなくなります。
ちなみに、テスト実行時にストレージとして使用するフォルダの設定は config/storage.yml
にある。
Active Storage の概要 - 2 セットアップで設定した部分。
local:
service: Disk
root: <%= Rails.root.join("storage") %>
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %> # これ
amazon:
service: S3
access_key_id: ""
secret_access_key: ""
この設定を他のディレクトリにしているときは、 remove_uploaded_files.rb
内の、クリーンアップするフォルダの指定も合わせて変えないといけないはず。
def remove_uploaded_files
FileUtils.rm_rf(Rails.root.join('tmp', 'storage')) # ここ
end
環境
Windows 10
Ubuntu 18.04.1 LTS (Windows Subsystem for Linux)
Ruby 2.5.3
Rails 5.2.3
参考
How do I test a file upload in rails?
色々調べているうちにこのページを読んで、どうやらRails5のActiveStorageを使う場合ではやり方が違いそう?と思ってRailsガイドを読み直した。
0 件のコメント:
コメントを投稿