2009-07-24 9 views
91

Ich habe einen Controller, der für das Akzeptieren von JSON-Dateien zuständig ist und dann die JSON-Dateien verarbeitet, um eine Benutzerwartung für unsere Anwendung durchzuführen. Im Benutzer-Test funktioniert das Hochladen und Verarbeiten der Datei, aber natürlich würde ich gerne den Testprozess der Benutzer-Wartung in unseren Tests automatisieren. Wie kann ich im Rahmen des Funktionstests eine Datei auf einen Controller hochladen?Wie kann ich einen Datei-Upload in Rails testen?

Antwort

99

Gesucht wurde diese Frage und ich konnte sie nicht finden, oder ihre Antwort auf Stack Overflow, aber ich fand sie woanders, also möchte ich sie auf SO verfügbar machen.

Die Schienen Rahmen hat eine Funktion fixture_file_upload (Rails 2Rails 3, Rails 5), das Fixtures Verzeichnis für die angegebene Datei suchen und wird es als eine Testdatei für den Controller in der Funktionsprüfung zur Verfügung stellen. Um es zu verwenden:

1) Legen Sie Ihre Datei in den Test in Ihrem Fixtures/Files-Unterverzeichnis zum Testen hochgeladen.

2) In Ihrem Komponententest können Sie Ihre Testdatei durch Aufruf von fixture_file_upload ('Pfad', 'MIME-Typ') abrufen.

z.B .:

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

3) die Post-Methode aufrufen, die Controller-Aktion Sie zu schlagen, um das Objekt von fixture_file_upload als Parameter für den Upload wieder vorbei.

zB:

post :bookmark, :bulkfile => bulk_json

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

Dies wird den simulierten Post-Prozess unter Verwendung einer Tempfile Kopie der Datei in Ihrem Armaturen Verzeichnis durchlaufen und dann auf das Gerät zurückgeben testen, damit Sie mit den Ergebnissen des Beitrags beginnen können.

+2

Dies funktioniert nicht auf Schienen 3. Die action_controller/test_process-Datei ist nicht in activesupport 3 scheint es. Ich habe eine neue Frage für das gleiche hier geöffnet - http://StackOverflow.com/Questions/3966263/attachment-fu-testing-in-Rails-3 – Chirantan

+0

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

+0

Daumen hoch & vielen Dank! –

4

Sie möchten fixtures_file_upload verwenden. Sie werden Ihre Testdatei in ein Unterverzeichnis des Fixtures-Verzeichnisses legen und dann den Pfad zu fixtures_file_upload übergeben. Hier ist ein example of code, mit Befestigungsdatei

9

Vom Rspec Buch hochladen, B13.0:

Rails' bietet eine Action :: TestUploadedFile Klasse, die verwendet werden kann, eine hochgeladene Datei im params-Hash ein darzustellen Controller-Spezifikation, wie folgt:

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 Bild test_avatar.png 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.

+1

Ich bekomme eine "nicht initialisierte Konstante ActionController :: TestUploadedFile" Fehler, wenn ich einen Test mit diesem Code ausführen. Alles andere, was ich in der Datei benötigen würde? –

+0

Es scheint bereits in Rails 2.3 veraltet zu sein. Ab Rails 3.0 [[so geht's]] (http://apidock.com/rails/ActionDispatch/TestProcess/fixture_file_upload) mit Fixtures – Sebastialonso

0

wenn Sie bekommen die Datei in Ihrem Controller mit folgenden

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

dann versuchen Sie folgendes in Ihren Angaben:

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 

Dies wird die gefälschte Methode machen ‚tempfile‘ Methode, was den Pfad zur geladenen Datei zurückgibt.

76

Mori's Antwort ist korrekt, außer dass in Rails 3 anstelle von "ActionController :: TestUploadedFile.new" "Rack :: Test :: UploadedFile.new" verwendet werden muss.

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

Diese Methode ist eine gute Alternative, wenn sich Ihre Fixtures nicht in/test/fixtures befinden. Wenn Sie zum Beispiel dynamisch einige Dateien für die Tests generieren, befinden sie sich möglicherweise in einem/tmp-Ordner. –

+2

Dies funktioniert auch mit Rails 4 einwandfrei. Vielen Dank! – Waseem

22

Ich denke, es ist besser, die neue ActionDispatch verwenden :: Http :: UploadedFile diese Weise:

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 die gleichen Methoden verwenden, können Sie in Ihrem Validierungen verwenden (wie zum Beispiel Tempdatei).

1

Wenn Sie Standardschienen Test mit Fabrik Mädchen verwenden. Fein 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 werden Dummy-Bild in /test/images/100_100.jpg zu halten haben.

Es funktioniert perfekt.

Prost!

Verwandte Themen