Como faço para testar o upload de um arquivo no Rails?

102

Eu tenho um controlador que é responsável por aceitar arquivos JSON e, em seguida, processar os arquivos JSON para fazer alguma manutenção de usuário para nosso aplicativo. No teste do usuário, o upload do arquivo e o processamento funcionam, mas é claro que gostaria de automatizar o processo de teste da manutenção do usuário em nosso teste. Como posso fazer upload de um arquivo para um controlador na estrutura de teste funcional?

animal
fonte

Respostas:

110

Procurei esta pergunta e não consegui encontrar, ou sua resposta no Stack Overflow, mas encontrei em outro lugar, então estou pedindo para disponibilizá-la no SO.

O framework Rails tem uma função fixture_file_upload( Rails 2 Rails 3 , Rails 5 ), que irá pesquisar seu diretório de fixtures pelo arquivo especificado e irá disponibilizá-lo como um arquivo de teste para o controlador no teste funcional. Para usá-lo:

1) Coloque seu arquivo a ser carregado no teste no subdiretório de fixtures / files para teste.

2) Em seu teste de unidade, você pode obter seu arquivo de teste chamando fixture_file_upload ('path', 'mime-type').

por exemplo:

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

3) chame o método post para acertar a ação do controlador que você deseja, passando o objeto retornado por fixture_file_upload como parâmetro para o upload.

por exemplo:

post :bookmark, :bulkfile => bulk_json

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

Isso será executado através do pós-processo simulado usando uma cópia Tempfile do arquivo em seu diretório de fixtures e, em seguida, retornará ao seu teste de unidade para que você possa começar a examinar os resultados da publicação.

animal
fonte
2
Isso não funciona no rails 3. O arquivo action_controller / test_process não está disponível no activesupport 3, ao que parece. Abri uma nova pergunta para o mesmo aqui - stackoverflow.com/questions/3966263/…
Chirantan
O link em sua resposta é 404 ou é só para mim?
Ernest
@Chirantan foi movido para ActionDispatch :: TestProcess
ben author
como isso pode ser usado com FactoryGirl? stackoverflow.com/questions/34677780/…
Richlewis
85

A resposta de Mori está correta, exceto que no Rails 3 ao invés de "ActionController :: TestUploadedFile.new" você deve usar "Rack :: Test :: UploadedFile.new".

O objeto de arquivo criado pode então ser usado como um valor de parâmetro em testes 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
fonte
Este método é uma boa alternativa quando seus aparelhos não estão localizados em / test / fixtures. Se você gerar dinamicamente alguns arquivos para os testes, por exemplo, eles podem estar em uma pasta / tmp.
Olivier Amblet
25

Eu acho melhor usar o novo ActionDispatch :: Http :: UploadedFile desta forma:

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

Desta forma, você pode usar os mesmos métodos que está usando em suas validações (como por exemplo o arquivo temporário).

David Morales
fonte
8

Do The Rspec Book, B13.0:

Rails 'fornece uma classe ActionController :: TestUploadedFile que pode ser usada para representar um arquivo carregado no hash de parâmetros de uma especificação do controlador, como este:

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

Esta especificação requer que você tenha uma imagem test_avatar.png no diretório spec / fixtures. Ele pegaria esse arquivo, faria o upload para o controlador e o controlador criaria e salvaria um modelo de usuário real.

Mori
fonte
2
Recebo um erro "ActionController :: TestUploadedFile constante não inicializada" quando executo um teste com este código. Preciso de mais alguma coisa no arquivo?
Vini.g.fer
1
Parece estar obsoleto já em Rails 2.3. Para Rails 3.0 em diante, aqui está como você faz usando fixtures
Sebastialonso
4

Você deseja usar fixtures_file_upload . Você colocará seu arquivo de teste em um subdiretório do diretório fixtures e então passará o caminho para fixtures_file_upload. Aqui está um exemplo de código , usando upload de arquivo de fixação

Rob Di Marco
fonte
1

Se você estiver usando o teste de trilhos padrão com a Factory Girl. Bem abaixo do código.

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

Nota: você terá que manter uma imagem fictícia em /test/images/100_100.jpg.

Funciona perfeitamente.

Felicidades!

Manish Shrivastava
fonte
0

se você estiver obtendo o arquivo em seu controlador com o seguinte

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

em seguida, tente o seguinte em suas especificações:

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

Isso tornará o método falso para o método 'tempfile', que retornará o caminho para o arquivo carregado.

Esenbek Kydyr uulu
fonte