Wie teste ich einen Datei-Upload in Rails?


101

Ich habe einen Controller, der dafür verantwortlich ist, JSON-Dateien zu akzeptieren und dann die JSON-Dateien zu verarbeiten, um einige Benutzerwartungen für unsere Anwendung durchzuführen. Beim Benutzertest funktioniert das Hochladen und Verarbeiten von Dateien, aber natürlich möchte ich den Testprozess der Benutzerwartung in unseren Tests automatisieren. Wie kann ich eine Datei auf einen Controller im Framework für Funktionstests hochladen?

Antworten:


110

Ich habe nach dieser Frage gesucht und konnte sie oder ihre Antwort auf Stack Overflow nicht finden, habe sie aber an anderer Stelle gefunden. Deshalb bitte ich sie, sie auf SO verfügbar zu machen.

Das Rails-Framework verfügt über eine Funktion fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), die Ihr Fixtures-Verzeichnis nach der angegebenen Datei durchsucht und diese als Testdatei für den Controller beim Funktionstest zur Verfügung stellt. Um es zu benutzen:

1) Fügen Sie Ihre hochzuladende Datei zum Testen in das Unterverzeichnis Ihrer Geräte / Dateien zum Testen ein.

2) In Ihrem Unit-Test können Sie Ihre Testdatei abrufen, indem Sie fixture_file_upload ('path', 'mime-type') aufrufen.

z.B:

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

3) Rufen Sie die post-Methode auf, um die gewünschte Controller-Aktion auszuführen, und übergeben Sie das von fixture_file_upload zurückgegebene Objekt als Parameter für den Upload.

z.B:

post :bookmark, :bulkfile => bulk_json

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

Dies durchläuft den simulierten Post-Prozess mit einer Tempfile-Kopie der Datei in Ihrem Fixtures-Verzeichnis und kehrt dann zu Ihrem Komponententest zurück, damit Sie mit der Prüfung der Ergebnisse des Posts beginnen können.


2
Dies funktioniert nicht auf Schienen 3. Die Datei action_controller / test_process ist anscheinend nicht in activesupport 3 verfügbar. Ich habe eine neue Frage für das gleiche hier geöffnet
stackoverflow.com/questions/3966263/…

Der Link in Ihrer Antwort lautet 404, oder ist es nur für mich?
Ernest

@Chirantan es ist zu ActionDispatch :: TestProcess verschoben
ben Autor

Wie kann dies mit FactoryGirl verwendet werden? stackoverflow.com/questions/34677780/…
Richlewis

85

Moris Antwort ist richtig, außer dass Sie in Rails 3 anstelle von "ActionController :: TestUploadedFile.new" "Rack :: Test :: UploadedFile.new" verwenden müssen.

Das erstellte Dateiobjekt kann dann als Parameterwert in Rspec- oder TestUnit-Tests verwendet werden.

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

Diese Methode ist eine gute Alternative, wenn sich Ihre Geräte nicht in / test / fixtures befinden. Wenn Sie beispielsweise einige Dateien für die Tests dynamisch generieren, befinden sie sich möglicherweise stattdessen in einem Ordner / tmp.
Olivier Amblet

25

Ich denke, es ist besser, das neue ActionDispatch :: Http :: UploadedFile folgendermaßen zu verwenden:

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

Auf diese Weise können Sie dieselben Methoden verwenden, die Sie in Ihren Validierungen verwenden (z. B. tempfile).


8

Aus dem Rspec-Buch, B13.0:

Rails 'bietet eine ActionController :: TestUploadedFile-Klasse, mit der eine hochgeladene Datei im Parameter-Hash einer Controller-Spezifikation dargestellt werden kann:

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

Diese Spezifikation würde erfordern, dass Sie ein test_avatar.png-Image im Verzeichnis spec / fixtures haben. Es würde diese Datei nehmen, sie auf den Controller hochladen und der Controller würde ein echtes Benutzermodell erstellen und speichern.


2
Beim Ausführen eines Tests mit diesem Code wird der Fehler "Nicht initialisierte Konstante ActionController :: TestUploadedFile" angezeigt. Sonst noch etwas, das ich in der Datei benötigen würde?
Vini.g.fer

1
Es scheint bereits in Rails 2.3 veraltet zu sein. Für Rails 3.0 ab, hier ist , wie Sie es tun mit Geräten
Sebastialonso


1

Wenn Sie Standardschienen verwenden, testen Sie mit Factory Girl. Gut unter dem Code.

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

Hinweis: Sie müssen ein Dummy-Bild behalten /test/images/100_100.jpg.

Es funktioniert perfekt.

Prost!


0

Wenn Sie die Datei in Ihrem Controller wie folgt erhalten

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

Versuchen Sie dann Folgendes in Ihren Spezifikationen:

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

Dadurch wird die gefälschte Methode zur 'tempfile'-Methode, die den Pfad zur geladenen Datei zurückgibt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.