【问题标题】:How do I test a file upload in rails?如何在 Rails 中测试文件上传?
【发布时间】:2010-11-13 19:06:42
【问题描述】:

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

【问题讨论】:

    标签: ruby-on-rails ruby testing upload


    【解决方案1】:

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

    rails 框架有一个函数fixture_file_upload (Rails 2 Rails 3, Rails 5),它将在您的fixtures 目录中搜索指定的文件,并将其作为控制器的测试文件用于功能测试.要使用它:

    1) 把你要上传的文件放到你的fixtures/files子目录下进行测试。

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

    例如:

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

    3) 调用post方法点击你想要的控制器动作,将fixture_file_upload返回的对象作为上传参数传递。

    例如:

    post :bookmark, :bulkfile => bulk_json

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

    这将使用您的fixtures目录中的文件的临时文件副本运行模拟的后期处理,然后返回到您的单元测试,以便您可以开始检查后期的结果。

    【讨论】:

    【解决方案2】:

    Mori 的回答是正确的,除了在 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 文件夹中。
    【解决方案3】:

    我认为这样使用新的 ActionDispatch::Http::UploadedFile 会更好:

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

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

    【讨论】:

      【解决方案4】:

      来自 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 图像。它将获取该文件,将其上传到控制器, 控制器将创建并保存一个真实的用户模型。

      【讨论】:

      • 我在使用此代码运行测试时收到“未初始化的常量 ActionController::TestUploadedFile”错误。我还需要文件中的其他内容吗?
      • 它似乎早在 Rails 2.3 就被弃用了。对于 Rails 3.0 及以上版本,here's how you do it 使用固定装置
      【解决方案5】:

      您想使用fixtures_file_upload。您将把测试文件放在fixtures 目录的子目录中,然后将路径传递给fixtures_file_upload。这里是example of code,使用fixture文件上传

      【讨论】:

        【解决方案6】:

        如果您使用工厂女孩的默认 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 中保留一个虚拟图像。

        效果很好。

        干杯!

        【讨论】:

          【解决方案7】:

          如果您通过以下方式在控制器中获取文件

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

          【讨论】:

            猜你喜欢
            • 2015-01-24
            • 1970-01-01
            • 2011-04-22
            • 1970-01-01
            • 2011-11-07
            • 2016-07-24
            • 2014-07-28
            • 2019-10-27
            • 1970-01-01
            相关资源
            最近更新 更多