title: Ho to test file upload in Ruby on Rails 6 with minitest?
body: <p>I have controller method like this: </p>
  
  <pre class="lang-rb prettyprint-override"><code># POST /v1/scans
    def create
      p params
      uploaded_file = params["pm_file"]
      filename      = uploaded_file.original_filename
      content       = uploaded_file.read
      parser = ParserStrategy.parser_for filename
      file_scan = parser.parse_content content, filename, @api_token.organisation
  
      data = {'scan.id': file_scan.id.to_s}
      render json: data, status: :created 
    rescue =&gt; e
      Rails.logger.error e.message
      Rails.logger.error e.backtrace.join("\n")
    end
  </code></pre>
  
  <p>The file upload works fine. If I test it with CURL like this: </p>
  
  <pre><code>curl -H "Authorization: Bearer QGoEUTK5htI6IT1zyLgKWPqBxv1EXrf7ApSFuuSi" -X POST http://localhost:3000/v1/scans -F pm_file=@composer.json
  </code></pre>
  
  <p>I'm getting the expected results and the parameters output looks like this: </p>
  
  <pre><code>Parameters: {"pm_file"=&gt;#&lt;ActionDispatch::Http::UploadedFile:0x00007f914bae9708 @tempfile=#&lt;Tempfile:/var/folders/ng/h_lxfcf13m71_kgr70_f79hr0000gn/T/RackMultipart20200521-75565-r5a4k1.json&gt;, @original_filename="composer.json", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"pm_file\"; filename=\"composer.json\"\r\nContent-Type: application/octet-stream\r\n"&gt;}
  &lt;ActionController::Parameters {"pm_file"=&gt;#&lt;ActionDispatch::Http::UploadedFile:0x00007f914bae9708 @tempfile=#&lt;Tempfile:/var/folders/ng/h_lxfcf13m71_kgr70_f79hr0000gn/T/RackMultipart20200521-75565-r5a4k1.json&gt;, @original_filename="composer.json", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"pm_file\"; filename=\"composer.json\"\r\nContent-Type: application/octet-stream\r\n"&gt;, "controller"=&gt;"v1/scans", "action"=&gt;"create"} permitted: false&gt;
  </code></pre>
  
  <p>I can clearly see that <code>pm_file</code> is an Object of the type UploadedFile. Now I would like to write an automated test for it. Did so with minitest: </p>
  
  <pre class="lang-rb prettyprint-override"><code>test "should return 201 because valid request" do
    file_path = "#{Rails.root}/test/fixtures/files/composer/composer.json"
    composer_file = Rack::Test::UploadedFile.new(file_path, 'application/json', false)
    post v1_scans_url, params: { pm_file: composer_file }, headers: { "Authorization" =&gt; "Bearer #{@token}" }, as: :json
    assert_response 201
  end
  </code></pre>
  
  <p>Unfortunately that doesn't work. Then I fire the test the parameters output looks like this: </p>
  
  <pre><code>Parameters: {"pm_file"=&gt;{"original_filename"=&gt;"composer.json", "tempfile"=&gt;"#&lt;File:0x00007fd2a11dff30&gt;", "content_type"=&gt;"application/json"}, "scan"=&gt;{"pm_file"=&gt;{"original_filename"=&gt;"composer.json", "tempfile"=&gt;"#&lt;File:0x00007fd2a11dff30&gt;", "content_type"=&gt;"application/json"}}}
  </code></pre>
  
  <p>Now the <code>pm_file</code> is not an Object of the type UploadedFile anymore, it's a Hash. And the code is failing with: </p>
  
  <pre><code>undefined method `original_filename' for #&lt;ActionController::Parameters:0x00007fd2859c2278&gt;
  </code></pre>
  
  <p>The same happens with <code>fixture_file_upload</code>. This test brings exactly the same result: </p>
  
  <pre class="lang-rb prettyprint-override"><code>test "should return 201 because valid request" do
    file_path = "#{Rails.root}/test/fixtures/files/composer/composer.json"
    composer_file = fixture_file_upload("#{Rails.root}/test/fixtures/files/composer/composer.json",'application/json')
    post v1_scans_url, params: { pm_file: composer_file }, headers: { "Authorization" =&gt; "Bearer #{@token}" }, as: :json
    assert_response 201
  end
  </code></pre>
  
  <p>What I'm doing wrong? How to test a file upload in Rails 6 correctly? </p>