ฉันจะทดสอบการอัปโหลดไฟล์ในรางได้อย่างไร


102

ฉันมีคอนโทรลเลอร์ที่รับผิดชอบในการรับไฟล์ JSON จากนั้นประมวลผลไฟล์ JSON เพื่อทำการบำรุงรักษาผู้ใช้สำหรับแอปพลิเคชันของเรา ในการทดสอบผู้ใช้การอัปโหลดไฟล์และการประมวลผลทำงานได้ แต่แน่นอนว่าฉันต้องการทำให้กระบวนการทดสอบการบำรุงรักษาผู้ใช้เป็นไปโดยอัตโนมัติในการทดสอบของเรา ฉันจะอัปโหลดไฟล์ไปยังคอนโทรลเลอร์ในกรอบการทดสอบการทำงานได้อย่างไร

คำตอบ:


110

ค้นหาคำถามนี้แล้วไม่พบหรือไม่พบหรือคำตอบใน Stack Overflow แต่พบที่อื่นดังนั้นฉันจึงขอให้มันพร้อมใช้งานบน SO

เฟรมเวิร์กรางมีฟังก์ชันfixture_file_upload( Rails 2 Rails 3 , Rails 5 ) ซึ่งจะค้นหาไดเร็กทอรีการแข่งขันของคุณสำหรับไฟล์ที่ระบุและจะทำให้พร้อมใช้งานเป็นไฟล์ทดสอบสำหรับคอนโทรลเลอร์ในการทดสอบการทำงาน วิธีใช้:

1) วางไฟล์ของคุณที่จะอัปโหลดในการทดสอบในไดเร็กทอรีย่อย fixtures / files สำหรับการทดสอบ

2) ในการทดสอบหน่วยของคุณคุณสามารถรับไฟล์ทดสอบของคุณได้โดยเรียกใช้ fixture_file_upload ('path', 'mime-type')

เช่น:

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

3) เรียกใช้วิธีการโพสต์เพื่อกดการกระทำของคอนโทรลเลอร์ที่คุณต้องการส่งคืนวัตถุโดย fixture_file_upload เป็นพารามิเตอร์สำหรับการอัปโหลด

เช่น:

post :bookmark, :bulkfile => bulk_json

หรือใน Rails 5: post :bookmark, params: {bulkfile: bulk_json}

สิ่งนี้จะทำงานผ่านกระบวนการโพสต์จำลองโดยใช้สำเนาชั่วคราวของไฟล์ในไดเร็กทอรีการแข่งขันของคุณจากนั้นกลับไปที่การทดสอบหน่วยของคุณเพื่อให้คุณสามารถเริ่มตรวจสอบผลลัพธ์ของโพสต์ได้


2
สิ่งนี้ใช้ไม่ได้บนราง 3 ดูเหมือนว่าไฟล์ action_controller / test_process ไม่มีใน activesupport 3 ฉันเปิดคำถามใหม่เหมือนกันที่นี่ - stackoverflow.com/questions/3966263/…
Chirantan

ลิงก์ในคำตอบของคุณคือ 404 หรือมีไว้สำหรับฉันเท่านั้น
Ernest

@Chirantan ถูกย้ายไปที่ ActionDispatch :: TestProcess
ben ผู้เขียน

จะใช้กับ FactoryGirl ได้อย่างไร? stackoverflow.com/questions/34677780/…
Richlewis

86

คำตอบของ Mori ถูกต้องยกเว้นใน Rails 3 แทนที่จะเป็น "ActionController :: TestUploadedFile.new" คุณต้องใช้ "Rack :: Test :: UploadedFile.new"

จากนั้นอ็อบเจ็กต์ไฟล์ที่สร้างขึ้นสามารถใช้เป็นค่าพารามิเตอร์ในการทดสอบ Rspec หรือ 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

วิธีนี้เป็นทางเลือกที่ดีเมื่ออุปกรณ์ของคุณไม่ได้อยู่ใน / ทดสอบ / ส่วนควบ หากคุณสร้างไฟล์บางไฟล์สำหรับการทดสอบแบบไดนามิกไฟล์เหล่านั้นอาจอยู่ในโฟลเดอร์ a / tmp แทน
Olivier Amblet

25

ฉันคิดว่าดีกว่าถ้าใช้ ActionDispatch ใหม่ :: Http :: UploadFile ด้วยวิธีนี้:

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

ด้วยวิธีนี้คุณสามารถใช้วิธีการเดียวกับที่คุณใช้ในการตรวจสอบความถูกต้องของคุณ (เช่น tempfile)


8

จาก The Rspec Book, B13.0:

Rails 'มีคลาส ActionController :: TestUploadedFile ซึ่งสามารถใช้เพื่อแสดงไฟล์ที่อัปโหลดในแฮช params ของข้อมูลจำเพาะคอนโทรลเลอร์เช่นนี้:

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

ข้อกำหนดนี้ต้องการให้คุณมีอิมเมจ test_avatar.png ในไดเร็กทอรี spec / fixtures จะต้องใช้ไฟล์นั้นอัปโหลดไปยังคอนโทรลเลอร์จากนั้นคอนโทรลเลอร์จะสร้างและบันทึกโมเดลผู้ใช้จริง


2
ฉันได้รับข้อผิดพลาด "Uninitialized constant ActionController :: TestUploadedFile" เมื่อฉันเรียกใช้การทดสอบด้วยรหัสนี้ มีอะไรอีกบ้างที่ฉันต้องการในไฟล์นี้?
Vini.g ดู

1
ดูเหมือนว่าจะเลิกใช้งานเร็วที่สุดเท่าที่ Rails 2.3 สำหรับ Rails 3.0 เป็นต้นไปนี่คือวิธีการใช้อุปกรณ์ติดตั้ง
Sebastialonso

4

คุณต้องการที่จะใช้fixtures_file_upload คุณจะใส่ไฟล์ทดสอบของคุณในไดเร็กทอรีย่อยของไดเร็กทอรี fixtures จากนั้นส่งต่อในพา ธ ไปยัง fixtures_file_upload นี่คือตัวอย่างของโค้ดโดยใช้การอัปโหลดไฟล์ Fixture


1

หากคุณใช้การทดสอบรางเริ่มต้นกับสาวโรงงาน ปรับรหัสด้านล่าง

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

หมายเหตุ: คุณจะต้องเก็บภาพจำลอง/test/images/100_100.jpgไว้

มันทำงานได้อย่างสมบูรณ์

ไชโย!


0

หากคุณได้รับไฟล์ในคอนโทรลเลอร์ของคุณด้วยสิ่งต่อไปนี้

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

จากนั้นลองทำสิ่งต่อไปนี้ในข้อกำหนดของคุณ:

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

วิธีนี้จะทำให้เมธอดปลอมเป็นเมธอด 'tempfile' ซึ่งจะส่งคืนพา ธ ไปยังไฟล์ที่โหลด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.