Jak przetestować przesyłanie plików na railsach?


102

Mam kontroler, który jest odpowiedzialny za akceptowanie plików JSON, a następnie przetwarzanie plików JSON w celu wykonania pewnych czynności konserwacyjnych dla naszej aplikacji. W testowaniu użytkowników działa przesyłanie i przetwarzanie plików, ale oczywiście chciałbym zautomatyzować proces testowania obsługi użytkowników w naszych testach. Jak mogę przesłać plik do kontrolera w ramach testów funkcjonalnych?

Odpowiedzi:


110

Szukałem tego pytania i nie mogłem go znaleźć ani odpowiedzi na Stack Overflow, ale znalazłem je gdzie indziej, więc proszę o udostępnienie go na SO.

Framework rails posiada funkcję fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), która przeszuka katalog fixtures w poszukiwaniu określonego pliku i udostępni go jako plik testowy dla kontrolera podczas testów funkcjonalnych. Aby z niego skorzystać:

1) Umieść plik do przesłania do testu w podkatalogu fixtures / files do testów.

2) W swoim teście jednostkowym możesz pobrać plik testowy, wywołując fixture_file_upload („path”, „mime-type”).

na przykład:

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

3) wywołaj metodę post, aby wykonać żądaną akcję kontrolera, przekazując obiekt zwrócony przez fixture_file_upload jako parametr do załadowania.

na przykład:

post :bookmark, :bulkfile => bulk_json

Lub w Rails 5: post :bookmark, params: {bulkfile: bulk_json}

Spowoduje to przeprowadzenie symulowanego procesu końcowego przy użyciu kopii pliku Tempfile pliku w katalogu urządzeń, a następnie powrót do testu jednostkowego, aby można było rozpocząć badanie wyników wiadomości.


2
To nie działa na szynach 3. Wygląda na to, że plik action_controller / test_process nie jest dostępny w activesupport 3. Otworzyłem nowe pytanie na to samo tutaj - stackoverflow.com/questions/3966263/…
Chirantan

Link w Twojej odpowiedzi to 404, czy to tylko dla mnie?
Ernest,

@Chirantan został przeniesiony do ActionDispatch :: TestProcess
autor ben

jak można to wykorzystać z FactoryGirl? stackoverflow.com/questions/34677780/…
Richlewis

86

Odpowiedź Mori jest poprawna, z tym wyjątkiem, że w Railsach 3 zamiast "ActionController :: TestUploadedFile.new" musisz użyć "Rack :: Test :: UploadedFile.new".

Utworzony obiekt pliku może być następnie użyty jako wartość parametru w testach Rspec lub 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

Ta metoda jest dobrą alternatywą, gdy urządzenia nie znajdują się w katalogu / test / fixtures. Jeśli na przykład generujesz dynamicznie niektóre pliki do testów, mogą one znajdować się w folderze / tmp.
Olivier Amblet

25

Myślę, że lepiej jest użyć nowego ActionDispatch :: Http :: UploadedFile w ten sposób:

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

W ten sposób możesz użyć tych samych metod, których używasz w swoich walidacjach (jak na przykład plik tymczasowy).


8

Z książki Rspec, B13.0:

Rails udostępnia klasę ActionController :: TestUploadedFile, której można użyć do reprezentowania przesłanego pliku w skrócie parametrów specyfikacji kontrolera, na przykład:

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

Ta specyfikacja wymagałaby posiadania obrazu test_avatar.png w katalogu spec / fixtures. Musiałby pobrać ten plik, przesłać go do kontrolera, a kontroler utworzyłby i zapisałby prawdziwy model użytkownika.


2
Po uruchomieniu testu z tym kodem pojawia się błąd „niezainicjowana stała ActionController :: TestUploadedFile”. Czy potrzebowałbym czegoś jeszcze w pliku?
Vini.g.fer

1
Wydaje się, że jest przestarzały już w Railsach 2.3. W przypadku Rails 3.0 i nowszych, oto jak to zrobić za pomocą urządzeń
Sebastialonso,


1

Jeśli używasz domyślnych szyn, przetestuj z dziewczyną z fabryki. Dobrze poniżej kodu.

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

Uwaga: będziesz musiał zachować fikcyjny obraz w /test/images/100_100.jpg.

Działa doskonale.

Twoje zdrowie!


0

jeśli otrzymujesz plik w kontrolerze z następującym

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

następnie spróbuj wykonać następujące czynności w swoich specyfikacjach:

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

Spowoduje to, że fałszywa metoda stanie się metodą „tempfile”, która zwróci ścieżkę do załadowanego pliku.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.