kiểm tra tải lên tệp bằng rspec - rails


142

Tôi muốn kiểm tra một tệp tải lên trong đường ray, nhưng không chắc chắn làm thế nào để làm điều này.

Đây là mã điều khiển:

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

Tôi đã thử thông số này, nhưng nó không hoạt động:

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

Làm cách nào tôi có thể mô phỏng tệp tải lên, sử dụng rspec?

Câu trả lời:


291

Bạn có thể sử dụng fixture_file_upload phương pháp để kiểm tra tập tin tải lên: Đặt tập tin thử nghiệm của bạn trong "{} Rails.root / spec / fixtures / file" thư mục

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

Trong trường hợp bạn đang mong đợi tệp ở dạng 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
Điều này nên được đánh dấu là câu trả lời, bởi vì nó là chính xác. Cảm ơn người đàn ông!
Emil Ahlbäck

30
Xem bit.ly/OSrL7R (câu hỏi tràn ngăn xếp 3966263) nếu bạn nhận được tệp không tồn tại lỗi. Một hình thức khác là cần thiết trong Rails 3.2: @file = Rack :: Test :: UploadedFile.new (Rails.root.join ('spec / đạc / files / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload cũng hoạt động nếu bạn chỉ định đường dẫn đầy đủ đến tệp: "Rails.root.join ('spec / đạc / files / test.csv"
jmanrubia

1
fixture_file_upload đang được coi là một chuỗi trong params, có ai biết tại sao không?
Abe Petrillo

3
@AbePetrillo (hoặc bất cứ ai nhìn thấy bình luận và có cùng câu hỏi) Tôi đã có cùng một vấn đề. Trong trường hợp của tôi, đối số đầu tiên postlà một phương thức của trình trợ giúp đường dẫn, mà đối số dự định duy nhất mà tôi không bao gồm trong ngoặc đơn, vì vậy các mã thông báo sau được hiểu là các đối số bổ sung cho trình trợ giúp, thay vì lập luận cho chính bài đăng. Ví dụ, tôi đã post order_documents_path @order, document: filethay vì post order_documents_path(@order), document: file.
soupdog

54

Tôi không chắc chắn nếu bạn có thể kiểm tra tải lên tệp bằng RSpec một mình. Bạn đã thử Capybara chưa?

Thật dễ dàng để kiểm tra tải lên tệp bằng attach_filephương pháp của capybara từ thông số yêu cầu.

Ví dụ: mã này chỉ là bản demo):

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
Tất nhiên điều này hoạt động trong một spec tích hợp. Câu hỏi của OP liên quan đến thông số kỹ thuật của bộ điều khiển, vì anh ta chỉ đăng mã điều khiển. Chỉ cần nói nếu có ai nhầm lẫn. Làm điều này trong một đặc điểm kỹ thuật, làm câu trả lời của ebsbk trong một thông số kỹ thuật đơn vị.
Starkers

2
Đường dẫn tệp cần được trích dẫn
sixty4bit 11/07/2015

32

nếu bạn bao gồm Rack :: Test *, chỉ cần bao gồm các phương thức kiểm tra

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

sau đó bạn có thể sử dụng phương thức UploadedFile:

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

* LƯU Ý: Ví dụ của tôi dựa trên Sinatra, mở rộng Rack, nhưng sẽ hoạt động với Rails, cũng sử dụng Rack, TTBOMK


3
FYI: Bạn không nhất thiết phải include Rack::Test::Methodssử dụng Rack :: Test :: UploadedFile. require 'rack/testLà đủ.
xentek

3
Tôi thậm chí không phải require 'rack/test'. nếu bạn đang sử dụng Rack::Test::UploadedFileđủ tốt để sử dụng nó. Cung cấp thiết lập ứng dụng đường ray của bạn là tốt. Tái bút: Tôi đang ở Rails 4ruby 2.1
Vishnu Narang

Nhận xét của Vishnu là chính xác nhất, vì anh ta yêu cầu phương pháp rõ ràng. Bao gồm rack/testsẽ bao gồm tất cả mọi thứ từ thử nghiệm, bao gồm test/methods, nhưng cũng bao gồm mọi thứ trong thử nghiệm, vì vậy có lẽ nhiều hơn bạn cần.
zedd45

18

Tôi chưa thực hiện điều này bằng RSpec, nhưng tôi có một bài kiểm tra Test :: Đơn vị thực hiện một cái gì đó tương tự để tải lên một bức ảnh. Tôi thiết lập tệp đã tải lên dưới dạng phiên bản ActionDispatch :: Http :: UploadedFile, như sau:

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

Một cái gì đó tương tự có thể làm việc cho bạn cũng.


6

Đây là cách tôi đã làm với Rails 6, RSpecRack::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

KHÔNG bao gồmActionDispatch::TestProcess hoặc bất kỳ mã nào khác trừ khi bạn chắc chắn về những gì bạn bao gồm.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.