web-dev-qa-db-ja.com

Railsでファイルのアップロードをテストするにはどうすればよいですか?

JSONファイルを受け入れ、JSONファイルを処理してアプリケーションのユーザーメンテナンスを行うコントローラーがあります。ユーザーのテストでは、ファイルのアップロードと処理は機能しますが、もちろん、テストでユーザーのメンテナンスをテストするプロセスを自動化したいと思います。機能テストフレームワークのコントローラーにファイルをアップロードするにはどうすればよいですか?

98
animal

この質問を検索し、Stack Overflowでその質問またはその答えを見つけることができませんでしたが、他の場所で見つけたので、SOで利用できるようにしています。

Railsフレームワークには関数_fixture_file_upload_があります( Rails 2RailsRails 5 ) 、指定したファイルをフィクスチャディレクトリで検索し、機能テストでコントローラのテストファイルとして使用できるようにします。

1)テスト用にfixtures/filesサブディレクトリのテストにアップロードするファイルを配置します。

2)単体テストでは、fixture_file_upload( 'path'、 'mime-type')を呼び出してテストファイルを取得できます。

例えば。:

bulk_json = fixture_file_upload('files/bulk_bookmark.json','application/json')

3)postメソッドを呼び出して、目的のコントローラーアクションをヒットし、fixture_file_uploadによって返されたオブジェクトをアップロードのパラメーターとして渡します。

例えば。:

_post :bookmark, :bulkfile => bulk_json_

またはRails 5:_post :bookmark, params: {bulkfile: bulk_json}_

これは、フィクスチャディレクトリ内のファイルのTempfileコピーを使用してシミュレートされたポストプロセスを実行し、ユニットテストに戻って、ポストの結果の調査を開始できます。

109
animal

森の答えは正しいですが、Rails 3では "ActionController :: TestUploadedFile.new"の代わりに "Rack :: Test :: UploadedFile.new"を使用する必要があります。

作成されたファイルオブジェクトは、RspecまたはTestUnitテストのパラメーター値として使用できます。

test "image upload" do
  test_image = path-to-fixtures-image + "/Test.jpg"
  file = Rack::Test::UploadedFile.new(test_image, "image/jpeg")
  post "/create", :user => { :avatar => file }
  # assert desired results
  post "/create", :user => { :avatar => file }     

  assert_response 201
  assert_response :success
end
83
Victor Grey

新しいActionDispatch :: Http :: UploadedFileを次のように使用する方が良いと思います:

uploaded_file = ActionDispatch::Http::UploadedFile.new({
    :tempfile => File.new(Rails.root.join("test/fixtures/files/test.jpg"))
})
assert model.valid?

このようにして、検証で使用しているのと同じメソッドを使用できます(たとえば、tempfile)。

23
David Morales

Rspec Book、B13.0から:

RailsにはActionController :: TestUploadedFileクラスが用意されており、次のようにコントローラー仕様のparamsハッシュでアップロードされたファイルを表すために使用できます。

describe UsersController, "POST create" do
  after do
    # if files are stored on the file system
    # be sure to clean them up
  end

  it "should be able to upload a user's avatar image" do
    image = fixture_path + "/test_avatar.png"
    file = ActionController::TestUploadedFile.new image, "image/png"
    post :create, :user => { :avatar => file }
    User.last.avatar.original_filename.should == "test_avatar.png"
  end
end

この仕様では、spec/fixturesディレクトリにtest_avatar.pngイメージが必要です。そのファイルを取り、コントローラーにアップロードすると、コントローラーは実際のユーザーモデルを作成して保存します。

8
Mori

fixtures_file_upload を使用します。テストファイルをフィクスチャディレクトリのサブディレクトリに配置してから、fixtures_file_uploadへのパスを渡します。 コードの例 で、フィクスチャファイルのアップロードを使用しています

4
Rob Di Marco

デフォルトを使用している場合Railsファクトリーガールでテストします。コード以下で問題ありません。

factory :image_100_100 do
    image File.new(File.join(::Rails.root.to_s, "/test/images", "100_100.jpg"))
end

注:/test/images/100_100.jpgにダミーイメージを保持する必要があります。

完璧に機能します。

乾杯!

1

次のようにしてコントローラーでファイルを取得している場合

json_file = params[:json_file]
FileUtils.mv(json_file.tempfile, File.expand_path('.')+'/tmp/newfile.json')

次に、仕様で次のことを試してください。

json_file = mock('JsonFile')
json_file.should_receive(:tempfile).and_return("files/bulk_bookmark.json")
post 'import', :json_file => json_file
response.should be_success

これにより、偽のメソッドが 'tempfile'メソッドになり、ロードされたファイルへのパスが返されます。

0