2009-07-24 7 views
91

J'ai un contrôleur qui est responsable de l'acceptation des fichiers JSON, puis le traitement des fichiers JSON pour faire de la maintenance de l'utilisateur pour notre application. Dans l'essai de l'utilisateur le téléchargement et le traitement de fichier fonctionne, mais bien sûr je voudrais automatiser le processus de test de la maintenance de l'utilisateur dans nos tests. Comment puis-je télécharger un fichier sur un contrôleur dans le cadre de test fonctionnel?Comment tester un téléchargement de fichier dans des rails?

Répondre

99

Recherche pour cette question et ne pouvait pas le trouver, ou sa réponse sur Stack Overflow, mais l'a trouvé ailleurs, donc je demande de le rendre disponible sur SO.

Le cadre de rails a une fixture_file_upload fonction (Rails 2Rails 3, Rails 5), qui recherche dans votre répertoire fixtures pour le fichier spécifié et il sera disponible en tant que fichier de test pour le contrôleur dans les tests fonctionnels. Pour l'utiliser:

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

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) appeler la méthode post pour frapper l'action du contrôleur que vous voulez, passer 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 se déroulera à travers le processus de simulation de poste en utilisant une copie fichier temporaire du fichier dans votre répertoire fixtures, puis revenez à votre unité test afin que vous puissiez commencer à examiner les résultats de la poste.

+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 - http://stackoverflow.com/questions/3966263/attachment-fu-testing-in-rails-3 – Chirantan

+0

Le lien dans votre réponse est 404, ou est-ce juste pour moi? – Ernest

+0

Pouce en l'air et merci beaucoup! –

4

Vous souhaitez utiliser fixtures_file_upload. Vous placerez votre fichier de test dans un sous-répertoire du répertoire fixtures, puis vous passerez le chemin vers fixtures_file_upload. Voici un example of code, en utilisant le fichier de montage télécharger

9

De Le Livre Rspec, B13.0:

Rails' fournit une ActionController :: class TestUploadedFile qui peut être utilisé pour représenter un fichier téléchargé dans le hachage params d'un spec du 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 exige que vous avez une image test_avatar.png dans la spécification/fixtures. Il prendrait ce fichier, le chargerait sur le contrôleur, et le contrôleur créerait et enregistrerait un vrai modèle d'utilisateur.

+1

Je reçois une erreur "constante non initialisée ActionController :: TestUploadedFile" lorsque j'exécute un test avec ce code. Y at-il autre chose que je devrais exiger dans le fichier? –

+0

Il semble être obsolète dès Rails 2.3. Pour Rails 3.0 et suivants, [voici comment vous le faites] (http://apidock.com/rails/ActionDispatch/TestProcess/fixture_file_upload) en utilisant les appareils – Sebastialonso

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 rendra la méthode faux à la méthode « tempfile », qui va retourner le chemin vers le fichier chargé.

76

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 
+0

Cette méthode est une bonne alternative lorsque vos appareils ne se trouvent pas dans/test/fixtures. Si vous générez dynamiquement des fichiers pour les tests par exemple, ils peuvent être dans un dossier/tmp à la place. –

+2

Cela fonctionne parfaitement avec Rails 4 aussi. Merci! – Waseem

22

je pense qu'il est préférable d'utiliser la nouvelle ActionDispatch :: Http :: UploadedFile ainsi:

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 validateurs (comme par exemple tempfile).

1

Si vous utilisez le test de rails par défaut avec factory girl. Très bien sous le code.

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

Note: vous devrez garder une image factice dans /test/images/100_100.jpg.

Cela fonctionne parfaitement.

À la votre!

Questions connexes