Заглушка многостраничных запросов с помощью webmock / rspec

Некоторое время я пытался заглушить многостраничные запросы с помощью 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 => {})

Конечно, я не могу последовать этому предложению, потому что границы генерируются динамически. Есть идеи, как правильно заглушить эти запросы?

Спасибо! Бруно


person Kamchatka    schedule 13.03.2013    source источник


Ответы (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
person camagu    schedule 08.01.2015
comment
Значит, заглушка ничего не возвращает? - person Steven Aguilar; 19.02.2019
comment
что ты хочешь что то вернуть? - person Steven Aguilar; 19.02.2019
comment
К вашему сведению, теперь кажется, что это лучше сделать с Rack::Request.new(env).POST, а не с Rack::Multipart::Parser.new(env).parse - person elliotcm; 22.10.2019

WebMock в настоящее время не поддерживает составные запросы. Дополнительную информацию можно найти в комментарии автора: https://github.com/vcr/vcr/issues/295#issuecomment-20181472

Предлагаю вам рассмотреть один из следующих путей:

  • заглушка без соответствия составному телу столба
  • упаковка запроса в метод с аргументами пути к файлу и установка более детального ожидания для этого метода
  • использование видеомагнитофона для имитации внешних запросов в интеграционных тестах
person jurglic    schedule 12.08.2013

Вот обходной путь с использованием WebMock с регулярным выражением для соответствия запросам multipart / form-data, особенно удобно для тестирования загрузки изображений:

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.

person Magne    schedule 23.01.2017