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?

pengguna727403
sumber

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
ebsbk
sumber
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
Ken
sumber
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

zedd45
sumber
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.

Dave Isaacs
sumber
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 .

ini adalah desainku
sumber
4

Saya harus menambahkan keduanya termasuk untuk membuatnya berfungsi:

describe "my test set" do
  include Rack::Test::Methods
  include ActionDispatch::TestProcess
nfriend21
sumber
1
Jangan pernah menyertakan ActionDispatch :: penjelasan TestProcess
gotar