uji unggah file menggunakan rspec-rails


142

Saya ingin menguji unggahan file di rails, tetapi saya tidak yakin bagaimana melakukan ini.

Berikut adalah kode pengontrol:

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

Saya telah mencoba spesifikasi ini, tetapi tidak berhasil:

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

Bagaimana saya bisa mensimulasikan unggahan file, menggunakan rspec?

Jawaban:


291

Anda dapat menggunakan fixture_file_upload metode untuk file tes upload: Letakkan file pengujian Anda di "{Rails.root} / spesifikasi / perlengkapan / file" direktori

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

Jika Anda mengharapkan file dalam bentuk params ['unggah'] ['datafile']

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

8
Ini harus ditandai sebagai jawabannya, karena sudah benar. Terima kasih sobat!
Emil Ahlbäck

30
Lihat bit.ly/OSrL7R (stack overflow question 3966263) jika Anda mendapatkan file tidak ada kesalahan. Diperlukan bentuk lain di Rails 3.2: @file = Rack :: Test :: UploadedFile.new (Rails.root.join ('spec / fixtures / file / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload juga berfungsi jika Anda menentukan path lengkap ke file: "Rails.root.join ('spec / fixtures / file / test.csv"
jmanrubia

1
fixture_file_upload sedang diperlakukan sebagai string dalam params, ada yang tahu mengapa?
Abe Petrillo

3
@AbePetrillo (atau siapa pun yang melihat komentar dan memiliki pertanyaan yang sama) Saya memiliki masalah yang sama. Dalam kasus saya, argumen pertama postadalah metode path helper, yang satu-satunya argumen yang saya maksud tidak dimasukkan dalam tanda kurung, jadi token berikut ditafsirkan sebagai argumen tambahan untuk helper, bukan argumen untuk posting itu sendiri. Misalnya, saya post order_documents_path @order, document: filemalah ganti post order_documents_path(@order), document: file.
soupdog

54

Saya tidak yakin apakah Anda dapat menguji unggahan file menggunakan RSpec saja. Sudahkah Anda mencoba Capybara ?

Sangat mudah untuk menguji unggahan file menggunakan attach_filemetode capybara dari spec permintaan.

Misalnya (kode ini hanya demo):

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
Tentu saja ini berfungsi dalam spesifikasi integrasi. Pertanyaan OP adalah mengenai spesifikasi unit pengontrol, mengingat dia hanya memposting kode pengontrol. Hanya mengatakan kalau ada yang bingung. Lakukan ini di spec fitur, lakukan jawaban ebsbk dalam spec unit.
Starkers

2
Path file harus dalam tanda kutip
sixty4bit

32

jika Anda memasukkan Rack :: Test *, cukup sertakan metode pengujian

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

maka Anda dapat menggunakan metode UploadedFile:

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

* CATATAN: Contoh saya didasarkan pada Sinatra, yang memanjang Rack, tetapi harus bekerja dengan Rails, yang juga menggunakan Rack, TTBOMK


3
FYI: Anda tidak harus include Rack::Test::Methodsmenggunakan Rack :: Test :: UploadedFile. require 'rack/testcukup.
xentek

3
Aku bahkan tidak harus melakukannya require 'rack/test'. jika Anda menggunakan Rack::Test::UploadedFileitu cukup baik untuk menggunakannya. Asalkan pengaturan aplikasi rel Anda baik-baik saja. PS: Saya aktif Rails 4danruby 2.1
Wisnu Narang

Komentar Wisnu adalah yang paling akurat, karena ia membutuhkan metode ini secara eksplisit. Termasuk rack/testakan mencakup segala sesuatu dari tes, yang termasuk test/methods, tetapi juga mencakup semua yang diuji, jadi mungkin lebih dari yang Anda butuhkan.
zedd45

18

Saya belum melakukan ini menggunakan RSpec, tetapi saya memiliki Test :: Unit test yang melakukan sesuatu yang serupa untuk mengunggah foto. Saya mengatur file yang diunggah sebagai instance dari ActionDispatch :: Http :: UploadedFile, sebagai berikut:

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

Hal serupa mungkin juga berlaku untuk Anda.


6

Beginilah cara saya melakukannya Rails 6, RSpecdanRack::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

JANGAN sertakanActionDispatch::TestProcess atau kode lain apa pun kecuali Anda yakin tentang apa yang Anda sertakan .


4

Saya harus menambahkan keduanya termasuk untuk membuatnya berfungsi:

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

1
Jangan pernah menyertakan ActionDispatch :: penjelasan TestProcess
gotar
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.