如何在Rails中测试文件上传?


101

我有一个控制器,它负责接受JSON文件,然后处理JSON文件以对我们的应用程序进行一些用户维护。在用户测试中,文件上载和处理工作正常,但是我当然想在测试中自动化测试用户维护的过程。如何在功能测试框架中将文件上传到控制器?

Answers:


110

搜索了这个问题,但找不到它,或者它在Stack Overflow上的答案,但在其他地方找到了它,所以我想在SO上提供它。

rails框架具有一个功能fixture_file_uploadRails 2 Rails 3Rails 5),它将在您的灯具目录中搜索指定的文件,并将其用作功能测试中控制器的测试文件。要使用它:

1)将要上传的文件放在测试中的fixtures / files子目录中进行测试。

2)在单元测试中,您可以通过调用Fixture_file_upload('path','mime-type')获得测试文件。

例如:

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

3)调用post方法以击中所需的控制器动作,并将fix_file_upload返回的对象作为上载参数传递。

例如:

post :bookmark, :bulkfile => bulk_json

或在Rails 5中: post :bookmark, params: {bulkfile: bulk_json}

这将使用Fixtures目录中的文件的Tempfile副本在模拟的发布过程中运行,然后返回到单元测试,以便您可以开始检查发布的结果。


2
这在rails 3上不起作用。action_controller / test_process文件似乎在activesupport 3中不可用。我已经打开了新的问题,对于同样在这里- stackoverflow.com/questions/3966263/...
Chirantan

您的答案中的链接是404,还是只适合我?
欧内斯特(Ernest)2010年

@Chirantan,它已移至ActionDispatch :: TestProcess
Ben作者

如何与FactoryGirl一起使用?stackoverflow.com/questions/34677780/…–
Richlewis

85

森的答案是正确的,除了在Rails 3中必须使用“ Rack :: Test :: UploadedFile.new”而不是“ ActionController :: TestUploadedFile.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

当您的灯具不在/ test / fixtures中时,此方法是一种不错的选择。例如,如果您为测试动态生成一些文件,则它们可能位于/ tmp文件夹中。
Olivier Amblet 2012年

25

我认为最好以这种方式使用新的ActionDispatch :: Http :: UploadedFile:

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

这样,您可以使用在验证中使用的相同方法(例如tempfile)。


8

从Rspec书,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

此规范要求您在spec / fixtures目录中具有一个test_avatar.png图像。它将获取该文件,将其上传到控制器,然后控制器将创建并保存一个真实的用户模型。


2
使用此代码运行测试时,出现“未初始化的常量ActionController :: TestUploadedFile”错误。文件中还需要其他内容吗?
Vini.g.fer 2015年

1
它似乎早在Rails 2.3中就已被弃用。为Rails 3.0起,这里是它的你怎么做用灯具
Sebastialonso


1

如果您对工厂女孩使用默认的rails测试。细读以下代码。

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'方法,这将返回已加载文件的路径。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.