Question

I am just a little confused at why I can't stub a local variable in my controller spec.

Here is my controller:

Class UsersController < ApplicationController
    ...
    def get_company
        resp = Net::HTTP.get("http://get_company_from_user_id.com/#{params[:id]}.json")
        @resp = JSON.parse(resp.body)
        ...

My spec looks like:

class ResponseHelper
    def initialize(body)
        @body = body
    end
end

describe "Get company" do
it "returns successful response" do
        stub_resp_body = '{"company": "example"}' 
        stub_resp = ResponseHelper.new(stub_resp_body)
    controller.stub!(:resp).and_return(stub_resp)
    get :get_company, {:id => @test_user.id}
    expect(response.status).to eq(200)
    end
end

I still get an error saying that:

 Errno::ECONNREFUSED:
 Connection refused - connect(2)

What am I doing wrong? If I am stubbing the resp variable why is it still trying to do the HTTP request and how would I stub the resp variable in this case?

Was it helpful?

Solution

You just cannot stub a local variable, you can only stub methods. In your case you can stub the Net::HTTP.get method:

Net::HTTP.stub(:get).and_return(stub_resp)

OTHER TIPS

There is no such thing as 'stubbing a local variable'. The only thing that can be stubbed are method calls.

You would need the stub the Net::HTTP.get call to return something that looks like a Net::HTTPResponse that the rest of your code can work with.

I quite often like to tidy this up by having a client class for each api that knows how to generate the url from the arguments (in this case the id) and how to parse the response. This keeps those details out of the controller and also makes testing easy, since now you can provide a mock client object

You cannot stub a local variable. Just a method. As there were answers above you may want to stub Net::HTTP.get call. However, if you don't want to have you code rely upon a particular HTTP client library you can extract the http request into another method of a controller and stub this method

Class UsersController < ApplicationController
...
def get_company
    resp = make_request(params[:id)
    @resp = JSON.parse(resp.body)
end

protected

def make_request(id)
  Net::HTTP.get('http://get_company_from_user_id.com/#{id}.json')
end


controller.
  should_receive(:make_request).
  with(@test_user.id).
  and_return(stub_resp)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top