ทดสอบการอัพโหลดไฟล์โดยใช้ 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 / ข้อมูลจำเพาะ / / ติดตั้งไฟล์"ไดเรกทอรี

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 :: UploadFile.new (Rails.root.join ('ข้อมูลจำเพาะ / การแข่งขัน / ไฟล์ / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload ยังใช้งานได้หากคุณระบุพา ธ เต็มไปยังไฟล์: "Rails.root.join ('ข้อมูลจำเพาะ / ไฟล์ติดตั้ง / ไฟล์ / test.csv"
jmanrubia

1
fixture_file_upload กำลังถูกใช้เป็นสตริงใน params ใคร ๆ ก็รู้ว่าทำไม
Abe Petrillo

3
@AbePetrillo (หรือใครก็ตามที่เห็นความคิดเห็นและมีคำถามเดียวกัน) ฉันมีปัญหาเดียวกัน ในกรณีของฉันอาร์กิวเมนต์แรกpostคือเมธอดตัวช่วยพา ธ ซึ่งมีเพียงอาร์กิวเมนต์ที่ตั้งใจไว้เท่านั้นที่ฉันไม่ได้ใส่ไว้ในวงเล็บดังนั้นโทเค็นต่อไปนี้ถูกตีความว่าเป็นอาร์คเพิ่มเติมต่อผู้ช่วยเหลือมากกว่า args สำหรับโพสต์เอง เช่นผมมีแทนpost order_documents_path @order, document: file post order_documents_path(@order), document: file
soupdog

54

ฉันไม่แน่ใจว่าคุณสามารถทดสอบการอัปโหลดไฟล์โดยใช้ RSpec เพียงอย่างเดียวได้ไหม คุณเคยลองCapybaraหรือยัง?

ง่ายต่อการทดสอบการอัปโหลดไฟล์โดยใช้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

จากนั้นคุณสามารถใช้เมธอด UploadFile ได้:

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

* หมายเหตุ: ตัวอย่างของฉันขึ้นอยู่กับ Sinatra ซึ่งขยาย Rack แต่ควรทำงานกับ Rails ซึ่งใช้ Rack, TTBOMK


3
FYI: คุณไม่จำเป็นต้องinclude Rack::Test::Methodsใช้ Rack :: Test :: UploadFile require 'rack/testก็เพียงพอแล้ว
xentek

3
ฉันไม่จำเป็นต้องทำrequire 'rack/test'ด้วยซ้ำ ถ้าคุณใช้Rack::Test::UploadedFileมันก็ดีพอที่จะใช้ ให้การติดตั้งแอพพลิเคชั่น Rails ของคุณเป็นเรื่องปกติ PS: ฉันอยู่Rails 4และruby 2.1
พระนารายณ์ Narang

ความคิดเห็นของพระนารายณ์นั้นถูกต้องที่สุดในขณะที่เขาต้องการวิธีการอย่างชัดเจน การรวมrack/testจะรวมทุกอย่างจากการทดสอบซึ่งรวมถึงtest/methodsแต่รวมถึงทุกอย่างในการทดสอบด้วยดังนั้นอาจมากกว่าที่คุณต้องการ
zedd45

18

ฉันยังไม่ได้ใช้ RSpec แต่มี Test :: Unit test ที่ทำสิ่งที่คล้ายกันสำหรับการอัปโหลดภาพถ่าย ฉันตั้งค่าไฟล์ที่อัปโหลดเป็นตัวอย่างของ ActionDispatch :: Http :: UploadFile ดังนี้

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.