Ali*_*urn 4 ruby rack functional-testing
为了测试,我将 Rack::Request 直接发送到应用程序,而不是使用服务器。
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
Run Code Online (Sandbox Code Playgroud)
非常适合测试直接输入,但我被文件上传所困扰。我的真实系统通过文件上传在浏览器中运行良好。但是现在我想通过 API 对其进行测试,并且不知道如何通过任何 Rack 类/方法将文件内容放入请求中。(我尝试理解 Rack::Test::UploadedFile 但没有成功)。
谢谢,阿利斯泰尔
你绝对是在正确的道路上。您甚至可以在request_via_API不进行任何修改的情况下使用您的函数,例如:
request_via_API(app, 'POST', '/', {
:field => "value",
:text_source => Rack::Multipart::UploadedFile.new(PATH_TO_YOUR_FILE, MIME_TYPE_OF_YOUR_FILE)
})
Run Code Online (Sandbox Code Playgroud)
这意味着您需要在某处放置一些文件。如果您使用夹具,您的测试上传文件应该围绕它们。您可以省略 MIME 时间,但默认为text/plain.
如果您使用准系统 Rack,您会在调用后得到以下哈希值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"
}
}
Run Code Online (Sandbox Code Playgroud)
当然,text_source密钥可以有任何其他名称。
Rack::MockRequest#env_for 如果出现以下情况,将自动尝试创建多部分表单数据请求:
:input提供选项:params 选项是一个 Hash:params 选项值至少包含一个实例 Rack::Multipart::UploadedFile我认为依赖于多部分请求生成,Rack::MockRequest并且Rack::Multipart仅用于模拟具有相同文件上传和文件上传机制的 HTML 表单。所以,没有必要直接使用Rack::Multipart#build_multipartor Rack::Multipart::Generator。
如果您有更复杂的多部分场景或不同的文件上传机制,则必须opts使用:inputkey 而不是:paramsto传递参数Rack::MockRequest#env_for。:input就机架模拟功能而言,如何为其生成该值是您的问题。只有StringIO当它是 a时才会将其包裹起来,String正如您在此处看到的那样。否则,它将与rack.input在 Rack 环境散列中传递的内容相同,因此它必须符合Rack 输入流规范(即,是一个IO类似对象)。
因为这对我来说也是一个很大的挑战,我用它作为练习来加深我对 Rack 的了解,所以我在 GitHub 上创建了一个简单的项目来探索这个文件上传模拟。
注意:我尝试将所有内容修复到 Rack 1.5.2,除了到 Rack SPEC 的链接(所以要小心)。指向 Ruby StdLib 的链接指向当前版本。