rspec - rails kullanarak dosya yüklemeyi test etme


142

Bir dosya yüklemesini raylarda test etmek istiyorum, ancak bunu nasıl yapacağımdan emin değilim.

Denetleyici kodu şöyledir:

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

Bu spec denedim, ama çalışmıyor:

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 kullanarak dosya yüklemeyi nasıl simüle edebilirim?

Yanıtlar:


291

Dosya yüklemeyi test etmek için fixture_file_upload yöntemini kullanabilirsiniz : Test dosyanızı "{Rails.root} / spec / fikstürleri / files" dizinine yerleştirin

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

Dosyayı parametre şeklinde bekliyorsanız ['upload'] ['datafile']

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

8
Bu cevap olarak işaretlenmelidir, çünkü doğrudur. Teşekkürler dostum!
Emil Ahlbäck

30
Dosya alıyorsanız, bit.ly/OSrL7R (yığın taşması sorusu 3966263) bölümüne bakın . Rails 3.2'de farklı bir form gerekiyor: @file = Rack :: Test :: UploadedFile.new (Rails.root.join ('spec / fikstür / dosyalar / test.csv'), 'text / csv')
Mike Blyth

3
fixture_file_upload ayrıca dosyanın tam yolunu belirtirseniz çalışır: "Rails.root.join ('spec / fikstür / dosyalar / test.csv"
jmanrubia

1
fixture_file_upload parametrelerde bir dize olarak değerlendiriliyor, nedenini bilen var mı?
Abe Petrillo

3
@AbePetrillo (ya da kim yorumu görür ve aynı soruyu varsa) Ben de aynı sorunu vardı. Benim durumumda, ilk argüman post, sadece amaçlanan argümanı parantez içine almadığım bir yol yardımcı yöntemiydi, bu nedenle aşağıdaki tokenler, yazının kendisi için argümanlar yerine yardımcıya ek argümanlar olarak yorumlandı. Örneğin, ben post order_documents_path @order, document: fileyerine post order_documents_path(@order), document: file.
soupdog

54

Yalnızca RSpec kullanarak dosya yüklemelerini test edip edemeyeceğinizden emin değilim. Capybara'yı denedin mi mi?

Dosya yüklemelerini capybara kullanarak test etmek kolaydır attach_file bir istek spesifikasyonundan yöntemini .

Örneğin (bu kod yalnızca bir demodur):

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
Tabii ki bu bir entegrasyon spesifikasyonunda çalışıyor. OP'nin sorusu, yalnızca denetleyici kodunu gönderdiği göz önüne alındığında bir denetleyici birimi spesifikasyonu ile ilgilidir. Sadece birinin kafasının karışıp karışmadığını söylemek. Bunu bir özellik spesifikasyonunda yapın, ebsbk'nin bir birim spesifikasyonundaki cevabını yapın.
Starkers

2
Dosya yolunun tırnak içinde olması gerekir
sixty4bit

32

Rack :: Test * eklerseniz, test yöntemlerini eklemeniz yeterlidir

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

UploadedFile yöntemini kullanabilirsiniz:

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

* NOT: Örneğim Rack'u genişleten Sinatra'ya dayanıyor, ancak Rack, TTBOMK kullanan Rails ile çalışmalı


3
Bilginize: include Rack::Test::MethodsRack :: Test :: UploadedFile kullanmak zorunda değilsiniz . require 'rack/testyeterlidir.
xentek

3
Ben bile gerek yok require 'rack/test'. Eğer kullanıyorsanız Rack::Test::UploadedFilebu kullanmak iyi yeterli. Raylar uygulama kurulumunun iyi olması şartıyla. PS: Ben varım Rails 4veruby 2.1
Vishnu Narang

Vishnu'nun yorumu, yöntemi açıkça gerektirdiği için en doğrudur. Dahil rack/testiçerir testi, her şeyi içerecek test/methods, aynı zamanda içerir şeyi öylesine muhtemelen daha ihtiyacınız daha testinde.
16:16

18

Bunu RSpec kullanarak yapmadım, ancak bir fotoğraf yüklemek için benzer bir şey yapan bir Test :: Unit testim var. Yüklenen dosyayı aşağıdaki gibi ActionDispatch :: Http :: UploadedFile örneği olarak ayarladım:

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

Benzer bir şey sizin için de işe yarayabilir.


6

Ben böyle olsun yaptığım nasıl Rails 6, RSpecveRack::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

Neleri eklediğinizdenActionDispatch::TestProcess emin değilseniz, başka kod yazmayın.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.