Come si verifica un caricamento di file in rails?


102

Ho un controller che è responsabile dell'accettazione dei file JSON e quindi dell'elaborazione dei file JSON per eseguire la manutenzione dell'utente per la nostra applicazione. Nel test dell'utente, il caricamento e l'elaborazione del file funzionano, ma ovviamente vorrei automatizzare il processo di test della manutenzione dell'utente nel nostro test. Come posso caricare un file su un controller nel framework di test funzionale?

Risposte:


110

Ho cercato questa domanda e non sono riuscito a trovarla, o la sua risposta su Stack Overflow, ma l'ho trovata altrove, quindi sto chiedendo di renderla disponibile su SO.

Il framework rails ha una funzione fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), che cercherà nella directory dei dispositivi il file specificato e lo renderà disponibile come file di test per il controller durante i test funzionali. Per usarlo:

1) Metti il ​​tuo file da caricare nel test nella tua sottodirectory fixtures / files per il test.

2) Nel tuo unit test puoi ottenere il tuo file di test chiamando fixture_file_upload ('path', 'mime-type').

per esempio:

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

3) chiama il metodo post per premere l'azione del controller che desideri, passando l'oggetto restituito da fixture_file_upload come parametro per l'upload.

per esempio:

post :bookmark, :bulkfile => bulk_json

O in Rails 5: post :bookmark, params: {bulkfile: bulk_json}

Questo eseguirà il post-processo simulato utilizzando una copia del file Tempfile nella directory dei dispositivi e quindi tornerà al test dell'unità in modo da poter iniziare a esaminare i risultati del post.


2
Questo non funziona su rails 3. Il file action_controller / test_process non è disponibile in activesupport 3 a quanto pare. Ho aperto una nuova domanda per lo stesso qui - stackoverflow.com/questions/3966263/...
Chirantan

Il link nella tua risposta è 404 o è solo per me?
Ernest

@Chirantan è stato spostato in ActionDispatch :: TestProcess
ben autore

come può essere utilizzato con FactoryGirl? stackoverflow.com/questions/34677780/...
Richlewis

85

La risposta di Mori è corretta, tranne che in Rails 3 invece di "ActionController :: TestUploadedFile.new" devi usare "Rack :: Test :: UploadedFile.new".

L'oggetto file creato può quindi essere utilizzato come valore di parametro nei test Rspec o 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

Questo metodo è una buona alternativa quando i tuoi dispositivi non si trovano in / test / fixtures. Se si generano dinamicamente alcuni file per i test, ad esempio, potrebbero essere invece in una cartella / tmp.
Olivier Amblet,

25

Penso che sia meglio usare il nuovo ActionDispatch :: Http :: UploadedFile in questo modo:

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

In questo modo puoi usare gli stessi metodi che stai usando nelle tue validazioni (come ad esempio tempfile).


8

Da The Rspec Book, B13.0:

Rails fornisce una classe ActionController :: TestUploadedFile che può essere utilizzata per rappresentare un file caricato nell'hash dei parametri di una specifica del controller, in questo modo:

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

Questa specifica richiederebbe di avere un'immagine test_avatar.png nella directory spec / fixtures. Richiederebbe quel file, lo caricherà sul controller e il controller creerà e salverà un modello utente reale.


2
Ottengo un errore "ActionController :: TestUploadedFile costante non inizializzato" quando eseguo un test con questo codice. C'è qualcos'altro che dovrei richiedere nel file?
Vini.g.fer

1
Sembra essere deprecato già da Rails 2.3. Per Rails 3.0 in poi, ecco come lo fai usando i dispositivi
Sebastialonso


1

Se stai usando i rails predefiniti, prova con factory girl. Bene sotto il codice.

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

Nota: dovrai mantenere un'immagine fittizia in formato /test/images/100_100.jpg.

Funziona perfettamente.

Saluti!


0

se stai ottenendo il file nel tuo controller con quanto segue

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

quindi prova quanto segue nelle tue specifiche:

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

Questo renderà il metodo falso al metodo 'tempfile', che restituirà il percorso al file caricato.

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.