使用rspec-rails测试文件上载

use*_*403 138 tdd file-upload ruby-on-rails rspec-rails

我想在rails中测试文件上传,但我不知道如何做到这一点.

这是控制器代码:

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
Run Code Online (Sandbox Code Playgroud)

我已经尝试过这个规范,但它不起作用:

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
Run Code Online (Sandbox Code Playgroud)

如何使用rspec模拟文件上传?

ebs*_*sbk 287

您可以使用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
Run Code Online (Sandbox Code Playgroud)

如果您期望以params ['upload'] ['datafile']的形式存在该文件

it "can upload a license" do
  file = Hash.new
  file['datafile'] = @file
  post :uploadLicense, :upload => file
  response.should be_success
end
Run Code Online (Sandbox Code Playgroud)

  • 如果您收到文件不存在错误,请参阅http://bit.ly/OSrL7R(堆栈溢出问题3966263).Rails 3.2中需要一个不同的形式:@file = Rack :: Test :: UploadedFile.new(Rails.root.join('spec/fixtures/files/test.csv'),'text/csv') (29认同)
  • 这应该标记为答案,因为它是正确的.谢啦! (8认同)
  • 如果指定文件的完整路径,fixture_file_upload也可以工作:"Rails.root.join('spec/fixtures/files/test.csv" (3认同)
  • @AbePetrillo(或看到评论并有相同问题的人)我遇到了同样的问题.在我的例子中,`post`的第一个参数是一个路径助手方法,它唯一的参数我没有用括号括起来,所以下面的标记被解释为助手的附加参数,而不是帖子本身的args.例如,我有`post order_documents_path @order,document:file`而不是`post order_documents_path(@order),document:file`. (3认同)

Ken*_*Ken 53

我不确定你是否可以单独使用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
Run Code Online (Sandbox Code Playgroud)

  • 当然,这适用于集成规范.OP的问题是关于控制器单元规格,考虑到他只发布控制器代码.只是说如果有人感到困惑.在功能规范中执行此操作,在单位规格中执行ebsbk的答案. (6认同)
  • 文件路径必须在引号中 (2认同)

zed*_*d45 31

如果你包括Rack :: Test*,只需包含测试方法

describe "my test set" do
  include Rack::Test::Methods
Run Code Online (Sandbox Code Playgroud)

然后你可以使用UploadedFile方法:

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

*注意:我的示例基于Sinatra,它扩展了Rack,但应该使用Rails,它也使用Rack,TTBOMK

  • 仅供参考:你不一定要"包括Rack :: Test :: Methods"来使用Rack :: Test :: UploadedFile.`require'rack/test`就足够了. (3认同)
  • 我甚至不需要'要求'机架/测试'.如果你使用的是'Rack :: Test :: UploadedFile`,那就足够好了.如果您的rails应用程序设置正常.PS:我在'Rails 4`和'ruby 2.1`上 (3认同)

Dav*_*acs 16

我没有使用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
Run Code Online (Sandbox Code Playgroud)

类似的东西也适合你.


thi*_*ign 13

我就是这样做的Rails 6RSpec并且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
Run Code Online (Sandbox Code Playgroud)

ActionDispatch::TestProcess除非您确定要包含的内容,否则请勿包含或任何其他代码。