Ruby-on-Rails, Net::HTTPResponse NoMethodError:undefined method `closed?' for nil:NilClass
Hello, I have faced an issue: I use the RSpec framework and I need to mock a response within a method which I test.
here is a sample of the method:
def perform_request
response = DataClient.new.request(arg: 'some_arg')
# do some thing with the response
end
RSpec file:
describe '#perform_request'
let(:response) do
Net::HTTPResponse.new(1.0, 200, "OK")
end
let(:double_response) {double('DataClient', request: response)}
before do
response.body = {some_key:some_value}.to_json
allow(DataClient).to receive(:new).and_return(double_response)
end
it 'returns a response body' do
MyClass.new.perform_request
expect(response.body).to eq({some_key:some_value}.to_json)
end
end
the problem happens when I try to call the 'body' method for the Net::HTTPResponse instance to read the body of it.
It throws the NoMethodError with the message "undefined method `closed?' for nil:NilClass" which I have no idea about.
I have tried to search for any explanation with question variations such as 'Net::HTTPResponse body undefined method closed?'', 'Ruby Net:: HTTPResponse body undefined method
closed?', 'Ruby undefined method `closed?' but couldn't find any relevant answer.
In advance, I have to say I can't use any other client library except the Net:: HTTP without any wrappers. Please don't advice it.
The point of the question is not just to get an explanation but also to get advice how to solve the problem. Thank you in advance for any explanation and advice.
The error is thrown because the instance of Net::HTTPResponse
you created in your test setup is trying to verify if the connection from which it expects to get data is closed.
I would not bother with creating an actual instance of Net::HTTPRequest
in your test setup. All your class knows is that DataClient.new.request
returns an object that responds to .body
. I would change your setup as follows:
let(:response){ instance_double(Net::HTTPResponse, body: response_body)}
let(:response_body) { { key: :value }.to_json }
Using an instance double instead of a real instance allows you to not have to worry about the actual implementation details of the class, while still getting the assurance that you are calling methods the class supports.