rspec-rails를 사용하여 파일 업로드 테스트


142

레일에서 파일 업로드를 테스트하고 싶지만 어떻게해야하는지 잘 모르겠습니다.

컨트롤러 코드는 다음과 같습니다.

def uploadLicense
    #Create the license object
    @license = License.create(params[:license]) 


    #Get Session ID
    sessid = session[:session_id]

    puts "\n\nSession_id:\n#{sessid}\n"

    #Generate a random string
    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
    newpass = ""
    1.upto(5) { |i| newpass << chars[rand(chars.size-1)] }

    #Get the original file name
    upload=params[:upload]
    name =  upload['datafile'].original_filename 

    @license.format = File.extname(name)

    #calculate license ID and location
    @license.location = './public/licenses/' + sessid + newpass + name 

    #Save the license file
    #Fileupload.save(params[:upload], @license.location) 
    File.open(@license.location, "wb") { |f| f.write(upload['datafile'].read) }

     #Set license ID
    @license.license_id = sessid + newpass

    #Save the license
    @license.save

    redirect_to :action => 'show', :id => @license.id 
end

이 사양을 시도했지만 작동하지 않습니다.

it "can upload a license and download a license" do
    file = File.new(Rails.root + 'app/controllers/lic.xml')
    license = HashWithIndifferentAccess.new
    license[:datafile] = file
    info = {:id => 4}
    post :uploadLicense, {:license => info, :upload => license}
end

rspec을 사용하여 파일 업로드를 어떻게 시뮬레이트 할 수 있습니까?

답변:


291

fixture_file_upload 메소드를 사용 하여 파일 업로드를 테스트 할 수 있습니다 . 테스트 파일을 "{Rails.root} / spec / fixtures / files" 디렉토리에 두십시오.

before :each do
  @file = fixture_file_upload('files/test_lic.xml', 'text/xml')
end

it "can upload a license" do
  post :uploadLicense, :upload => @file
  response.should be_success
end

params [ 'upload'] [ 'datafile'] 형식의 파일을 예상 한 경우

it "can upload a license" do
  file = Hash.new
  file['datafile'] = @file
  post :uploadLicense, :upload => file
  response.should be_success
end

8
정답이므로 답변으로 표시해야합니다. 고마워요!
Emil Ahlbäck

30
파일을 얻는 중 오류가 없으면 bit.ly/OSrL7R (스택 오버플로 질문 3966263)을 참조하십시오 . Rails 3.2에는 다른 형식이 필요합니다 : @file = Rack :: Test :: UploadedFile.new (Rails.root.join ( 'spec / fixtures / files / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload는 파일의 전체 경로를 지정하는 경우에도 작동합니다. "Rails.root.join ( 'spec / fixtures / files / test.csv"
jmanrubia

1
fixture_file_upload는 params에서 문자열로 취급되고 있습니다.
Abe Petrillo

3
@ AbePetrillo (또는 의견을보고 같은 질문을하는 사람)도 같은 문제가있었습니다. 필자의 경우 첫 번째 인수 post는 경로 도우미 메서드였습니다.이 메서드는 괄호로 묶지 않은 유일한 인수이므로 다음 토큰은 게시물 자체에 대한 인수가 아니라 도우미에 대한 추가 인수로 해석되었습니다. 예를 들어, post order_documents_path @order, document: file대신했습니다 post order_documents_path(@order), document: file.
soupdog

54

RSpec 만 사용하여 파일 업로드를 테스트 할 수 있는지 잘 모르겠습니다. 당신은 시도 카피 바라를 ?

attach_file요청 사양에서 capybara의 방법을 사용하여 파일 업로드를 쉽게 테스트 할 수 있습니다.

예를 들어 (이 코드는 데모 전용) :

it "can upload a license" do
  visit upload_license_path
  attach_file "uploadLicense", /path/to/file/to/upload
  click_button "Upload License"
end

it "can download an uploaded license" do
  visit license_path
  click_link "Download Uploaded License"
  page.should have_content("Uploaded License")
end

6
물론 이것은 통합 사양에서 작동합니다. OP의 질문은 컨트롤러 코드 만 게시한다는 점을 고려하여 컨트롤러 장치 사양에 관한 것입니다. 누군가 혼란스러워하면 기능 사양 에서이 작업을 수행하고 단위 사양에서 ebsbk의 답변을 수행하십시오.
Starkers

2
파일 경로는 따옴표로 묶어야합니다
sixty4bit

32

Rack :: Test *를 포함하는 경우 간단히 테스트 방법을 포함하십시오.

describe "my test set" do
  include Rack::Test::Methods

그런 다음 UploadedFile 메서드를 사용할 수 있습니다.

post "/upload/", "file" => Rack::Test::UploadedFile.new("path/to/file.ext", "mime/type")

* 참고 :이 예는 랙을 확장하는 Sinatra를 기반으로하지만 Rack, TTBOMK를 사용하는 Rails 와도 작동해야합니다.


3
참고 : include Rack::Test::MethodsRack :: Test :: UploadedFile을 반드시 사용할 필요는 없습니다 . require 'rack/test충분하다.
xentek

3
나는 할 필요조차 없다 require 'rack/test'. 당신이 Rack::Test::UploadedFile그것을 사용한다면 그것을 사용하기에 충분합니다. Rails 앱 설정이 정상입니다. PS : 나는에있어 Rails 4ruby 2.1
비슈누 나랑

비슈누의 의견은 그 방법을 명시 적으로 요구하기 때문에 가장 정확합니다. 포함하여 rack/test포함 테스트에 이르기까지 모든 것을 포함 할 것이다 test/methods, 또한 포함 모든 그래서 아마 당신이 필요로하는 것보다, 테스트를.
zedd45

18

RSpec을 사용 하여이 작업을 수행하지는 않았지만 사진 업로드와 비슷한 작업을 수행하는 Test :: Unit 테스트가 있습니다. 다음과 같이 업로드 된 파일을 ActionDispatch :: Http :: UploadedFile의 인스턴스로 설정했습니다.

test "should create photo" do
  setup_file_upload
  assert_difference('Photo.count') do
    post :create, :photo => @photo.attributes
  end
  assert_redirected_to photo_path(assigns(:photo))
end


def setup_file_upload
  test_photo = ActionDispatch::Http::UploadedFile.new({
    :filename => 'test_photo_1.jpg',
    :type => 'image/jpeg',
    :tempfile => File.new("#{Rails.root}/test/fixtures/files/test_photo_1.jpg")
  })
  @photo = Photo.new(
    :title => 'Uploaded photo', 
    :description => 'Uploaded photo description', 
    :filename => test_photo, 
    :public => true)
end

비슷한 것도 당신을 위해 작동 할 수 있습니다.


6

이것은 내가했던 방법입니다 Rails 6, RSpec그리고Rack::Test::UploadedFile

describe 'POST /create' do
  it 'responds with success' do
    post :create, params: {
      license: {
        picture: Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test-pic.png"),
        name: 'test'
      }
    }

    expect(response).to be_successful
  end
end

포함ActionDispatch::TestProcess 하는 내용이 확실하지 않은 경우 포함 하거나 다른 코드를 포함하지 마십시오 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.