prova un caricamento di file usando rspec - rails


142

Voglio testare un caricamento di file in rotaie, ma non sono sicuro di come farlo.

Ecco il codice del controller:

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

Ho provato questa specifica, ma non funziona:

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

Come posso simulare il caricamento del file, usando rspec?

Risposte:


291

È possibile utilizzare fixture_file_upload metodo per caricare file di test: Metti il tuo file di test in "{} Rails.root / spec / / file infissi" directory

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

Nel caso ti aspettassi il file sotto forma di parametri ['upload'] ['datafile']

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

8
Questo dovrebbe essere contrassegnato come risposta, perché è corretto. Grazie uomo!
Emil Ahlbäck,

30
Vedi bit.ly/OSrL7R (domanda di overflow dello stack 3966263) se stai ottenendo errori nel file non esistono. In Rails 3.2 è necessario un modulo diverso: @file = Rack :: Test :: UploadedFile.new (Rails.root.join ('spec / fixtures / files / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload funziona anche se si specifica il percorso completo del file: "Rails.root.join ('spec / fixtures / files / test.csv"
jmanrubia,

1
fixture_file_upload viene trattato come una stringa in params, qualcuno sa perché?
Abe Petrillo,

3
@AbePetrillo (o chiunque veda il commento e abbia la stessa domanda) ho avuto lo stesso problema. Nel mio caso, il primo argomento è poststato un metodo path helper, il cui unico argomento voluto non è stato racchiuso tra parentesi, quindi i seguenti token sono stati interpretati come argomenti aggiuntivi per l'helper, piuttosto che argomenti per il post stesso. Ad esempio, ho avuto post order_documents_path @order, document: fileinvece di post order_documents_path(@order), document: file.
Cane zuppa

54

Non sono sicuro di poter testare i caricamenti di file usando solo RSpec. Hai provato Capybara ?

È facile testare i caricamenti di file utilizzando il attach_filemetodo capybara da una specifica di richiesta.

Ad esempio (questo codice è solo una 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
Naturalmente questo funziona in una specifica di integrazione. La domanda di OP riguarda una specifica dell'unità di controllo, considerando che sta pubblicando solo il codice del controller. Sto solo dicendo se qualcuno è confuso. Fallo in una specifica di funzione, fai la risposta di ebsbk in una specifica di unità.
Starkers,

2
Il percorso del file deve essere tra virgolette
sixty4bit l'

32

se includi Rack :: Test *, includi semplicemente i metodi di test

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

quindi è possibile utilizzare il metodo UploadedFile:

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

* NOTA: il mio esempio si basa su Sinatra, che estende Rack, ma dovrebbe funzionare con Rails, che utilizza anche Rack, TTBOMK


3
Cordiali saluti: Non è necessario include Rack::Test::Methodsutilizzare Rack :: Test :: UploadedFile. require 'rack/testè abbastanza.
xentek,

3
Non devo nemmeno farlo require 'rack/test'. se lo stai usando Rack::Test::UploadedFileè abbastanza buono per usarlo. A condizione che la configurazione dell'app Rails sia corretta. PS: Sono acceso Rails 4eruby 2.1
Vishnu Narang il

Il commento di Vishnu è il più preciso, poiché richiede esplicitamente il metodo. Includere rack/testincluderà tutto dal test, che include test/methods, ma include anche tutto ciò che è in prova, quindi probabilmente più del necessario.
zedd45,

18

Non l'ho fatto usando RSpec, ma ho un Test :: Unit test che fa qualcosa di simile per caricare una foto. Ho impostato il file caricato come istanza di ActionDispatch :: Http :: UploadedFile, come segue:

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

Qualcosa di simile potrebbe funzionare anche per te.


6

Questo è come l'ho fatto con Rails 6, RSpeceRack::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

NON includereActionDispatch::TestProcess o qualsiasi altro codice a meno che tu non sia sicuro di ciò che stai includendo.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.