¿Cómo pruebo la carga de un archivo en rieles?

102

Tengo un controlador que es responsable de aceptar archivos JSON y luego procesar los archivos JSON para hacer un mantenimiento de usuario para nuestra aplicación. En las pruebas de usuario, la carga y el procesamiento de archivos funcionan, pero, por supuesto, me gustaría automatizar el proceso de prueba del mantenimiento del usuario en nuestras pruebas. ¿Cómo puedo cargar un archivo a un controlador en el marco de prueba funcional?

animal
fuente

Respuestas:

110

Busqué esta pregunta y no pude encontrarla, o su respuesta en Stack Overflow, pero la encontré en otro lugar, así que pido que esté disponible en SO.

El marco de rails tiene una función fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), que buscará en su directorio de accesorios el archivo especificado y lo hará disponible como un archivo de prueba para el controlador en pruebas funcionales. Para usarlo:

1) Ponga su archivo para ser cargado en la prueba en su subdirectorio fixtures / files para probar.

2) En su prueba unitaria, puede obtener su archivo de prueba llamando a fixture_file_upload ('ruta', 'mime-type').

p.ej:

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

3) llame al método de publicación para presionar la acción del controlador que desea, pasando el objeto devuelto por fixture_file_upload como el parámetro para la carga.

p.ej:

post :bookmark, :bulkfile => bulk_json

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

Esto se ejecutará a través del proceso de publicación simulada usando una copia Tempfile del archivo en su directorio de accesorios y luego regresará a su prueba unitaria para que pueda comenzar a examinar los resultados de la publicación.

animal
fuente
2
Esto no funciona en rieles 3. Parece que el archivo action_controller / test_process no está disponible en activesupport 3. Abrí una nueva pregunta para lo mismo aquí - stackoverflow.com/questions/3966263/…
Chirantan
El enlace en su respuesta es 404, ¿o es solo para mí?
Ernest
@Chirantan se movió a ActionDispatch :: TestProcess
ben autor
¿Cómo se puede usar esto con FactoryGirl? stackoverflow.com/questions/34677780/…
Richlewis
85

La respuesta de Mori es correcta, excepto que en Rails 3 en lugar de "ActionController :: TestUploadedFile.new" tienes que usar "Rack :: Test :: UploadedFile.new".

El objeto de archivo que se crea se puede utilizar como un valor de parámetro en las pruebas 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
Víctor Grey
fuente
Este método es una buena alternativa cuando sus dispositivos no están ubicados en / test / fixtures. Si genera dinámicamente algunos archivos para las pruebas, por ejemplo, podrían estar en una carpeta / tmp en su lugar.
Olivier Amblet
25

Creo que es mejor usar el nuevo ActionDispatch :: Http :: UploadedFile de esta manera:

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

De esta manera, puede usar los mismos métodos que está usando en sus validaciones (como por ejemplo tempfile).

David Morales
fuente
8

Desde The Rspec Book, B13.0:

Rails 'proporciona una clase ActionController :: TestUploadedFile que se puede usar para representar un archivo cargado en el hash params de una especificación de controlador, como este:

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

Esta especificación requeriría que tenga una imagen test_avatar.png en el directorio spec / fixtures. Tomaría ese archivo, lo cargaría en el controlador y el controlador crearía y guardaría un modelo de usuario real.

Mori
fuente
2
Recibo un error de "ActionController :: TestUploadedFile constante no inicializado" cuando ejecuto una prueba con este código. ¿Algo más que necesite solicitar en el archivo?
Vini.g.fer
1
Parece estar obsoleto desde Rails 2.3. Para Rails 3.0 en adelante, así es como se hace usando accesorios
Sebastialonso
4

Quieres usar fixtures_file_upload . Pondrá su archivo de prueba en un subdirectorio del directorio de accesorios y luego pasará la ruta a fixtures_file_upload. Aquí hay un ejemplo de código , usando la carga de archivos de accesorios

Rob Di Marco
fuente
1

Si está utilizando rieles predeterminados, pruebe con Factory Girl. Bien por debajo del código.

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

Nota: deberá mantener una imagen ficticia en formato /test/images/100_100.jpg.

Funciona perfectamente.

¡Salud!

Manish Shrivastava
fuente
0

si obtiene el archivo en su controlador con lo siguiente

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

luego intente lo siguiente en sus especificaciones:

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

Esto hará que el método falso sea el método 'tempfile', que devolverá la ruta al archivo cargado.

Esenbek Kydyr uulu
fuente