неверное количество аргументов в запросе Net::HTTP

В приложении Sinatra я пытаюсь создать собственную оболочку для Net::HTTP, но застрял на одном из своих тестов. Я использую Webmock, чтобы заглушить запрос и передать его методу request Net::HTTP. Я провожу тестирование с помощью RSpec. Ошибка, которую я получаю:

 Failure/Error: client.request(request)

 ArgumentError:
   wrong number of arguments (given 0, expected 1)
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/webmock-2.1.0/lib/webmock/http_lib_adapters/net_http.rb:279:in `method'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/webmock-2.1.0/lib/webmock/http_lib_adapters/net_http.rb:279:in `request_signature_from_request'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/webmock-2.1.0/lib/webmock/http_lib_adapters/net_http.rb:75:in `request'
 # ./lib/net_http.rb:19:in `request'
 # ./spec/net_http_spec.rb:21:in `block (2 levels) in <top (required)>'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:236:in `instance_exec'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:236:in `block in run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:478:in `block in with_around_and_singleton_context_hooks'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:435:in `block in with_around_example_hooks'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/hooks.rb:478:in `block in run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/hooks.rb:616:in `run_around_example_hooks_for'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/hooks.rb:478:in `run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:435:in `with_around_example_hooks'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:478:in `with_around_and_singleton_context_hooks'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example.rb:233:in `run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example_group.rb:581:in `block in run_examples'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example_group.rb:577:in `map'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example_group.rb:577:in `run_examples'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/example_group.rb:543:in `run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:119:in `block (3 levels) in run_specs'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:119:in `map'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:119:in `block (2 levels) in run_specs'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1680:in `with_suite_hooks'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:118:in `block in run_specs'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/reporter.rb:77:in `report'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:117:in `run_specs'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:93:in `run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:78:in `run'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:45:in `invoke'
 # /home/admin/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/exe/rspec:4:in `<top (required)>'
 # /home/admin/.rbenv/versions/2.3.0/bin/rspec:23:in `load'
 # /home/admin/.rbenv/versions/2.3.0/bin/rspec:23:in `<main>'

Строка 279 из net_http.rb (первая строка стека):

method = request.method.downcase.to_sym

который находится внутри метода:

module WebMock
  module NetHTTPUtility

    def self.request_signature_from_request(net_http, request, body = nil)
      ...

который вызывается в строке 75 того же файла:

def request(request, body = nil, &block)
  request_signature = WebMock::NetHTTPUtility.request_signature_from_request(self, request, body)

это метод, который я вызываю у своего клиента. Это мои файлы:

net_http.rb

class NetHttp

  def initialize(client)
    @client = client
  end

  def request(request)
    client.request(request)
  end

  private

  attr_reader :client

end

net_http_spec.rb

describe "NetHttp" do

  let(:client)   {Net::HTTP.new(VERIFY_URL.host, VERIFY_URL.port)}
  let(:net_http) {NetHttp.new(client)}

  it "sends a get request" do
    request  = request_with_path
    response = net_http.request(request)
    expect(response.code).to eq("200")
  end

  def request_with_path
    request = stub_request(:get, VERIFY_URL)
      .with(:headers => {
        'Accept'=>'*/*',
        'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
        'User-Agent'=>'Ruby'
        })
      .to_return(:status => 200, :body => '{"hello": "world"}', :headers => {})

    class << request
      attr_accessor :path
    end

    request.path = VERIFY_URL.request_uri
    request
  end

end

Последняя часть, где я добавляю атрибут на лету, заключалась в устранении другой ошибки. Это немного похоже на грязный взлом. Может быть, есть лучший способ сделать все это, который также помешает мне сделать это?

И в моем spec_helper.rb я добавил строку:

WebMock.disable_net_connect!(allow_localhost: true)

Я поместил содержимое запроса в метод request, и все вроде бы в порядке, я также использовал дубликат Net::HTTPRequest вместо веб-заглушки, но получаю ту же ошибку. Я не хочу заглушать клиент, потому что это моя тестируемая система. Я также просмотрел код метода request в документации по Ruby. Я не понимаю... откуда эта ошибка и как ее решить?


person Xirux Nefer    schedule 22.06.2016    source источник
comment
Попробуйте запустить rspec с параметром -b (по умолчанию rspec скрывает части обратной трассировки не из вашего приложения, что может заставить вас искать не в том месте)   -  person Frederick Cheung    schedule 22.06.2016
comment
@FrederickCheung Я обновил сообщение об ошибке.   -  person Xirux Nefer    schedule 22.06.2016
comment
Похоже, ваш поддельный объект запроса не имеет метода method, поэтому он вызывает метод method из объекта, который действительно ожидает аргумент   -  person Frederick Cheung    schedule 22.06.2016
comment
Я пошел по этому пути, но он просто продолжает запрашивать что-то еще, например, body_stream с методом read и т. д. и т. д.   -  person Xirux Nefer    schedule 22.06.2016


Ответы (1)


Вам не нужно использовать возвращаемое значение stub_request, как вы. Вы можете создать экземпляр Net::HTTP::Request как обычно.

person Frederick Cheung    schedule 22.06.2016
comment
Извините, я не понимаю... Мне нужно передать объект запроса в метод запроса. В продакшене он будет создан следующим образом: request = Net::HTTP::Get.new VERIFY_URL.request_uri, но если я передам это, Webmock предупредит меня, что реальные HTTP-соединения отключены. Я не хочу иметь какие-либо вызовы new внутри метода, потому что я хочу использовать внедрение зависимостей. - person Xirux Nefer; 22.06.2016
comment
Документы Webmock предполагают, что это должно быть хорошо. Возможно, вы неправильно формируете запрос? (Например, что такое VERIFY_URL) - person Frederick Cheung; 23.06.2016
comment
VERIFY_URL — это строка, содержащая объект URI с URL-адресом, к которому я хотел бы подключиться. Насколько я понимаю, webmock будет перехватывать запросы на этот URL-адрес и возвращать заглушенный ответ. - person Xirux Nefer; 23.06.2016
comment
Похоже, что это реальный объект URI, который может не совпадать с тем, что ожидает webmock - документы подразумевают, что это просто строка - person Frederick Cheung; 23.06.2016
comment
Я наконец понял твой ответ. Когда я делаю response = net_http.request(request), он автоматически использует заглушку. Так что если убрать первую строчку теста и назначение заглушки, то работает :) - person Xirux Nefer; 30.06.2016