I’m writing test using double/stub, and i want to return me a fake value, but instead i’m getting and fake value and real value. Here is my controller and spec files, model has nothing in it. Any ideas what am i doing wrong? My guess is i’m doing it completely wrong. P.s. i’m kinda new to spec and mock/stub things
controller:
def destroy
uri = URI('example.com')
request_params = {'requestId' => @session.id,
'merchantId' => MERCHANTID,
'locale' => LOCALE,
'partnerId' => PARTNERID,
'sessionId' => params[:id]
}
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Post.new uri.request_uri
request.set_form_data(request_params)
#request.content_type = 'application/x-www-form-urlencoded'
response = http.request request # Net::HTTPResponse object
json = ActiveSupport::JSON.decode(response.body)
puts '<<<<<<<<<'
puts json
if json['expireSessionRes']['isError'] == false
render :json => {:status => 'ok', :message => 'logged out'}
else
render :json => {:status => 'failed', :message => 'logout failed'}
end
end
spec file:
it "should correctly return isError false if logout was sucessful" do
SID = "123"
@data3 = {:id => SID}
delete :destroy, default_rest_params.merge(@data3)
response = double('http.request')
response.stub!(:body => '{"expireSessionRes"=>{"requestId"=>"72", "sessionId"=>"123", "isError"=>false, "desc"=>""}}')
puts response.body
end
receiving:
{"expireSessionRes"=>{"requestId"=>"94", "isError"=>true, "desc"=>"Session exipred", "errorCode"=>"-10011"}}
{"expireSessionRes"=>{"requestId"=>"72", "sessionId"=>"123", "isError"=>false, "desc"=>""}}
first comes from controller
second from stub
So the thing with mocking and stubbing is, you have to hook your mock objects up to your real code somehow… the
double('http.request')bit just creates a mock object called “http.request”, it doesn’t makehttp.requestreturn this object.What you need to do is stub the
requestmethod to return the mock response. But it’s going to be pretty difficult to inject a mock, because you don’t have access to thehttpobject in the block from your tests.Difficulty testing code is often a good sign that you need to refactor your code.
The simplest thing would be to replace the whole
Net::HTTP.startthing with a single lineand then you can test it by doing
(I assume you’re in a controller spec and you’re going to need the
responseobject that RSpec provides, so your mock can’t be stored in a variable calledresponse).But that is just glossing over the more important point that you should be extracting your remote service interaction out into a dedicated class and testing that separately, it doesn’t belong in the controller.
Hope that helps!