How to fake file upload when checking Ruby Rack serverless?

For testing purposes, I am sending the Rack :: Request directly to the application, without using a server.

def request_via_API( app, method, path, params={} ) # app should be API
  env = Rack::MockRequest.env_for( path, {:method => method, :params=>params}  )
  app.handle Rack::Request.new(env)
end

      

works fine for testing direct input, but file upload drowns me. My real system works fine with a file upload browser. But now I want to test it using the API and don't know how to get the file content in the request via any of the Rack classes / methods. (I tried to understand Rack :: Test :: UploadedFile but failed).

Thanks Alistair

+3


source to share


1 answer


You were definitely on the right track. You can even use your function request_via_API

without any changes, for example:

request_via_API(app, 'POST', '/', {
  :field => "value",
  :text_source => Rack::Multipart::UploadedFile.new(PATH_TO_YOUR_FILE, MIME_TYPE_OF_YOUR_FILE)
})

      

This means that you must have a file of some kind. If you are using fixtures, your test boot file should be around them. You can omit the MIME time, but the default is text/plain

.

If you are using barebones Rack you get the following hash after the call Rack::Multipart.parse_multipart

:

{
  "field" => "value",
  "text_source" => {
    :filename => File.basename(PATH_TO_YOUR_FILE),
    :type => MIME_TYPE_OF_YOUR_FILE,
    :name => "text_source",
    :tempfile => Tempfile.new("RackMultipart"), # copied from PATH_TO_YOUR_FILE
    :head => "Content-Disposition: form-data; name=\"text_source\"; filename=\"#{File.basename(PATH_TO_YOUR_FILE)}\"\r\n" +
             "Content-Type: #{MIME_TYPE_OF_YOUR_FILE}\r\n" +
             "Content-Length: #{BYTESIZE_OF_YOUR_FILE}\r\n"
  }
}

      

The key text_source

can have any other name, of course.

Rack::MockRequest#env_for

automatically tries to create a data query with multiple data if:



  • HTTP method not GET
  • missing option :input

  • :params

    - this is Hash

  • :params

    parameter values ​​contain at least one instance Rack::Multipart::UploadedFile

You can see the details in the source code here and here .

I think relying on generating multiple requests for Rack::MockRequest

and Rack::Multipart

only useful for mocking HTML forms with file uploads and file upload mechanisms that act the same. Thus, there is no need to directly use Rack::Multipart#build_multipart

or Rack::Multipart::Generator

.

If you have more complex multi-page scripts or another file upload mechanism, you must pass the argument as a opts

key :input

instead of :params

on . How you create this value for is your problem as it is about related Rack capabilities. It only wraps it in , if that 's how you can see. Otherwise, it is the same as what would be passed as in the hash environment of the Rack environment, and therefore must conform to the Rack input stream specification (i.e., be a -like object). Rack::MockRequest#env_for

:input

StringIO

String

rack.input

IO

Because it was quite a challenge for me and I used it as an exercise to deepen my knowledge of Rack I by creating a simple project on GitHub to explore this file by uploading a mock.

Note. I tried to fix everything in Rack 1.5.2 except for the Rack SPEC reference (so be careful). The Ruby StdLib references lead to the current version.

+2


source







All Articles