Comment tester un téléchargement de fichier dans les rails?

102

J'ai un contrôleur qui est chargé d'accepter les fichiers JSON, puis de traiter les fichiers JSON pour effectuer une maintenance utilisateur pour notre application. Lors des tests utilisateur, le téléchargement et le traitement des fichiers fonctionnent, mais bien sûr, je voudrais automatiser le processus de test de la maintenance utilisateur dans nos tests. Comment puis-je télécharger un fichier sur un contrôleur dans le cadre de test fonctionnel?

animal
la source

Réponses:

110

J'ai recherché cette question et je n'ai pas pu la trouver, ni sa réponse sur Stack Overflow, mais je l'ai trouvée ailleurs, je demande donc de la rendre disponible sur SO.

Le framework rails a une fonction fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), qui recherchera dans votre répertoire fixtures le fichier spécifié et le rendra disponible comme fichier de test pour le contrôleur lors des tests fonctionnels. Pour l'utiliser:

1) Mettez votre fichier à télécharger dans le test dans votre sous-répertoire fixtures / files pour le test.

2) Dans votre test unitaire, vous pouvez obtenir votre fichier de test en appelant fixture_file_upload ('path', 'mime-type').

par exemple:

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

3) appelez la méthode post pour atteindre l'action du contrôleur que vous souhaitez, en passant l'objet retourné par fixture_file_upload comme paramètre pour le téléchargement.

par exemple:

post :bookmark, :bulkfile => bulk_json

Ou dans Rails 5: post :bookmark, params: {bulkfile: bulk_json}

Cela passera par le post-processus simulé en utilisant une copie Tempfile du fichier dans votre répertoire fixtures, puis reviendra à votre test unitaire afin que vous puissiez commencer à examiner les résultats de la publication.

animal
la source
2
Cela ne fonctionne pas sur les rails 3. Le fichier action_controller / test_process n'est pas disponible dans activesupport 3, semble-t-il. J'ai ouvert une nouvelle question pour la même chose ici - stackoverflow.com/questions/3966263/…
Chirantan
Le lien dans votre réponse est 404, ou est-ce juste pour moi?
Ernest
@Chirantan, il est déplacé vers ActionDispatch :: TestProcess
Ben auteur
comment cela peut-il être utilisé avec FactoryGirl? stackoverflow.com/questions/34677780/…
Richlewis
86

La réponse de Mori est correcte, sauf que dans Rails 3 au lieu de "ActionController :: TestUploadedFile.new", vous devez utiliser "Rack :: Test :: UploadedFile.new".

L'objet fichier créé peut ensuite être utilisé comme valeur de paramètre dans les tests Rspec ou 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
Victor Gray
la source
Cette méthode est une bonne alternative lorsque vos appareils ne sont pas situés dans / test / fixtures. Si vous générez dynamiquement certains fichiers pour les tests par exemple, ils peuvent se trouver dans un dossier / tmp à la place.
Olivier Amblet du
25

Je pense qu'il est préférable d'utiliser le nouveau ActionDispatch :: Http :: UploadedFile de cette façon:

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

De cette façon, vous pouvez utiliser les mêmes méthodes que vous utilisez dans vos validations (comme par exemple tempfile).

David Morales
la source
8

Extrait du livre Rspec, B13.0:

Rails 'fournit une classe ActionController :: TestUploadedFile qui peut être utilisée pour représenter un fichier téléchargé dans le hachage de paramètres d'une spécification de contrôleur, comme ceci:

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

Cette spécification nécessiterait que vous ayez une image test_avatar.png dans le répertoire spec / fixtures. Il prendrait ce fichier, le téléchargerait sur le contrôleur, et le contrôleur créerait et enregistrerait un modèle utilisateur réel.

Mori
la source
2
J'obtiens une erreur "ActionController :: TestUploadedFile constante non initialisée" lorsque j'exécute un test avec ce code. Y a-t-il autre chose que j'aurais besoin d'exiger dans le fichier?
Vini.g.fer
1
Il semble être obsolète dès Rails 2.3. Pour Rails 3.0 et les versions ultérieures, voici comment procéder en utilisant des luminaires
Sebastialonso
4

Vous souhaitez utiliser fixtures_file_upload . Vous placerez votre fichier de test dans un sous-répertoire du répertoire fixtures puis passerez le chemin vers fixtures_file_upload. Voici un exemple de code , utilisant le téléchargement de fichier de fixture

Rob Di Marco
la source
1

Si vous utilisez des rails par défaut, testez avec Factory Girl. Bien en dessous du code.

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

Remarque: vous devrez conserver une image factice au format /test/images/100_100.jpg.

Cela fonctionne parfaitement.

À votre santé!

Manish Shrivastava
la source
0

si vous obtenez le fichier dans votre contrôleur avec les éléments suivants

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

puis essayez ce qui suit dans vos spécifications:

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

Cela transformera la fausse méthode en méthode «tempfile», qui renverra le chemin vers le fichier chargé.

Esenbek Kydyr uulu
la source