6

我一直在尝试使用 webmock 存根多部分请求,但没有找到令人满意的解决方案。

理想情况下,我想将请求存根如下:

stub_request(:post, 'http://test.api.com').with(:body => { :file1 => File.new('filepath1'), file2 => File.new('filepath2') })

但是,这似乎不起作用,并且 RSpec 抱怨该请求没有被存根。打印非存根请求:

stub_request(:post, "http://test.api.com").
     with(:body => "--785340\r\nContent-Disposition: form-data; name=\"file1\"; filename=\"filepath1\"\r\nContent-Type: text/plain\r\n\r\nhello\r\n--785340\r\nContent-Disposition: form-data; name=\"file2\"; filename=\"filepath2\"\r\nContent-Type: text/plain\r\n\r\nhello2\r\n--785340\r\n",
          :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>'664', 'Content-Type'=>'multipart/form-data; boundary=785340', 'User-Agent'=>'Ruby'}).
     to_return(:status => 200, :body => "", :headers => {})

当然,我不能真正遵循这个建议,因为边界是动态生成的。知道如何正确地存根这些请求吗?

谢谢!布鲁诺

4

3 回答 3

3

有点晚了,但我会为未来的溢出者和谷歌人留下一个答案。

我遇到了同样的问题,并将Rack::Multipart::Parser与 Webmock 结合使用作为解决方法。快速而肮脏的代码应该看起来像这样(警告:使用 activesupport 扩展):

stub_request(:post, 'sample.com').with do |req|
  env = req.headers.transform_keys { |key| key.underscore.upcase }
                   .merge('rack.input' => StringIO.new(req.body))
  parsed_request = Rack::Multipart::Parser.new(env).parse

  # Expectations:
  assert_equal parsed_request["file1"][:tempfile].read, "hello world"
end
于 2015-01-08T00:16:51.057 回答
2

WebMock 目前不支持多部分请求。在此处查看作者的评论以获取更多信息:https ://github.com/vcr/vcr/issues/295#issuecomment-20181472

我建议您考虑以下路线之一:

  • 不匹配后多部分正文的存根
  • 将请求包装在带有文件路径参数的方法中,并为此方法设置更细粒度的期望
  • 在集成测试中使用 VCR 模拟外部请求
于 2013-08-12T18:21:17.210 回答
1

这是使用带有正则表达式的 WebMock 来匹配多部分/表单数据请求的解决方法,特别适用于测试图像的上传:

stub_request(:post, 'sample.com').with do |req|

  # Test the headers.
  assert_equal req.headers['Accept'], 'application/json'
  assert_equal req.headers['Accept-Encoding'], 'gzip, deflate'
  assert_equal req.headers['Content-Length'], 796588
  assert_match %r{\Amultipart/form-data}, req.headers['Content-Type']
  assert_equal req.headers['User-Agent'], 'Ruby'

  # Test the body. This will exclude the image blob data which follow these lines in the body
  req.body.lines[1].match('Content-Disposition: form-data; name="FormParameterNameForImage"; filename="image_filename.jpeg"').size >= 1
  req.body.lines[2].match('Content-Type: img/jpeg').size >= 1

end

也可以使用正常的 WebMock 使用方式来仅测试标头,并且在子句stub_request(:post, 'sample.com').with(headers: {'Accept' => 'application/json})中根本不包含任何正文规范。with

于 2017-01-23T10:06:27.123 回答