rspecを使用してファイルのアップロードをテストする-Rails


142

Railsでファイルのアップロードをテストしたいのですが、これを行う方法がわかりません。

これがコントローラーコードです:

def uploadLicense
    #Create the license object
    @license = License.create(params[:license]) 


    #Get Session ID
    sessid = session[:session_id]

    puts "\n\nSession_id:\n#{sessid}\n"

    #Generate a random string
    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
    newpass = ""
    1.upto(5) { |i| newpass << chars[rand(chars.size-1)] }

    #Get the original file name
    upload=params[:upload]
    name =  upload['datafile'].original_filename 

    @license.format = File.extname(name)

    #calculate license ID and location
    @license.location = './public/licenses/' + sessid + newpass + name 

    #Save the license file
    #Fileupload.save(params[:upload], @license.location) 
    File.open(@license.location, "wb") { |f| f.write(upload['datafile'].read) }

     #Set license ID
    @license.license_id = sessid + newpass

    #Save the license
    @license.save

    redirect_to :action => 'show', :id => @license.id 
end

私はこの仕様を試しましたが、うまくいきません:

it "can upload a license and download a license" do
    file = File.new(Rails.root + 'app/controllers/lic.xml')
    license = HashWithIndifferentAccess.new
    license[:datafile] = file
    info = {:id => 4}
    post :uploadLicense, {:license => info, :upload => license}
end

rspecを使用してファイルのアップロードをシミュレートするにはどうすればよいですか?

回答:


291

Fixture_file_uploadメソッドを使用して、ファイルのアップロードをテストできます。テストファイルを「{Rails.root} / spec / fixtures / files」ディレクトリに配置します。

before :each do
  @file = fixture_file_upload('files/test_lic.xml', 'text/xml')
end

it "can upload a license" do
  post :uploadLicense, :upload => @file
  response.should be_success
end

params ['upload'] ['datafile']の形式のファイルを予期していた場合

it "can upload a license" do
  file = Hash.new
  file['datafile'] = @file
  post :uploadLicense, :upload => file
  response.should be_success
end

8
これは正しいので、これを答えとしてマークする必要があります。ありがとう!
EmilAhlbäck12年

30
ファイルが存在しないというエラーが表示される場合は、bit.ly / OSrL7R(スタックオーバーフローの質問3966263)を参照してください。Rails 3.2では別のフォームが必要です:@file = Rack :: Test :: UploadedFile.new(Rails.root.join( 'spec / fixtures / files / test.csv')、 'text / csv')
Mike Blyth

3
ファイルへのフルパスを指定した場合、fixture_file_uploadも機能します: "Rails.root.join( 'spec / fixtures / files / test.csv"
jmanrubia

1
Fixture_file_uploadはparamsで文字列として扱われていますが、誰もが理由を知っていますか?
阿部ペトリロ2013

3
@AbePetrillo(またはコメントを見て、同じ質問を持つ人)私は同じ問題を抱えていました。私の場合、への最初の引数postはパスヘルパーメソッドであり、その唯一の意図された引数は括弧で囲まなかったため、次のトークンは、投稿自体の引数ではなく、ヘルパーへの追加の引数として解釈されました。たとえば、のpost order_documents_path @order, document: file代わりに持っていましたpost order_documents_path(@order), document: file
スープドッグ

54

RSpecだけを使用してファイルのアップロードをテストできるかどうかはわかりません。カピバラを試しましたか?

attach_fileリクエスト仕様からカピバラのメソッドを使用してファイルのアップロードをテストするのは簡単です。

例(このコードはデモのみです):

it "can upload a license" do
  visit upload_license_path
  attach_file "uploadLicense", /path/to/file/to/upload
  click_button "Upload License"
end

it "can download an uploaded license" do
  visit license_path
  click_link "Download Uploaded License"
  page.should have_content("Uploaded License")
end

6
もちろん、これは統合仕様で機能します。OPの質問は、コントローラーユニットの仕様に関するものです。混乱している人がいるかどうかを言っているだけです。機能仕様でこれを行い、ユニット仕様でebsbkの回答を行います。
スターカーズ2014年

2
ファイルパスは引用符で
囲む

32

Rack :: Test *を含める場合は、単にテストメソッドを含めます

describe "my test set" do
  include Rack::Test::Methods

その後、UploadedFileメソッドを使用できます。

post "/upload/", "file" => Rack::Test::UploadedFile.new("path/to/file.ext", "mime/type")

*注:私の例はラックを拡張するシナトラに基づいていますが、ラック、TTBOMKも使用するレールで動作するはずです


3
参考:必ずしもinclude Rack::Test::MethodsRack :: Test :: UploadedFileを使用する必要はありません。require 'rack/test十分です
xentek 2013年

3
私もする必要はありませんrequire 'rack/test'。使用しRack::Test::UploadedFileている場合は、それで十分です。Railsアプリのセットアップに問題がない場合。PS:私は乗っRails 4ていますruby 2.1
Vishnu Narang 14年

Vishnuのコメントは、メソッドを明示的に要求しているため、最も正確です。含むがrack/test含まれるテストからすべてが含まれますtest/methodsが、また、含まれるすべてので、おそらくより多くのあなたが必要とするよりも、テスト中に。
zedd45 2016年

18

RSpecを使用してこれを行ったことはありませんが、写真のアップロードと同様のことを行うTest :: Unitテストがあります。次のように、アップロードしたファイルをActionDispatch :: Http :: UploadedFileのインスタンスとして設定します。

test "should create photo" do
  setup_file_upload
  assert_difference('Photo.count') do
    post :create, :photo => @photo.attributes
  end
  assert_redirected_to photo_path(assigns(:photo))
end


def setup_file_upload
  test_photo = ActionDispatch::Http::UploadedFile.new({
    :filename => 'test_photo_1.jpg',
    :type => 'image/jpeg',
    :tempfile => File.new("#{Rails.root}/test/fixtures/files/test_photo_1.jpg")
  })
  @photo = Photo.new(
    :title => 'Uploaded photo', 
    :description => 'Uploaded photo description', 
    :filename => test_photo, 
    :public => true)
end

同様のものがあなたのためにも働くかもしれません。


6

これは私がそれをやった方法ですRails 6RSpecそしてRack::Test::UploadedFile

describe 'POST /create' do
  it 'responds with success' do
    post :create, params: {
      license: {
        picture: Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test-pic.png"),
        name: 'test'
      }
    }

    expect(response).to be_successful
  end
end

含めないでください ActionDispatch::TestProcessあなたは含めているものについてのしていることを確認したりしない限り、他のコード。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.