我正在使用double / stub编写测试,我想给我一个假值,但我得到了假值和真值。这是我的控制器和spec文件,模型中没有任何内容。我有什么想法,我做错了什么?我的猜测是我完全错了。附:我对规范和模拟/存根事物都不熟悉
控制器:
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文件:
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
接收:
{"expireSessionRes"=>{"requestId"=>"94", "isError"=>true, "desc"=>"Session exipred", "errorCode"=>"-10011"}}
{"expireSessionRes"=>{"requestId"=>"72", "sessionId"=>"123", "isError"=>false, "desc"=>""}}
首先来自控制器 第二个来自存根
答案 0 :(得分:1)
因此,使用模拟和存根的事情是,你必须以某种方式将你的模拟对象挂钩到你的真实代码...... double('http.request')
位只是创建一个名为“http.request”的模拟对象,它没有' t使http.request
返回此对象。
您需要做的是存根request
方法以返回模拟响应。但是注入模拟会非常困难,因为您无法从测试中访问块中的http
对象。
难以测试代码通常是您需要重构代码的好兆头。
最简单的方法是用一行替换整个Net::HTTP.start
事物
response = Net::HTTP.post_form(uri, request_params)
然后你可以通过
来测试它remote_response = double('remote_response', body: '...')
Net::HTTP.stub(:post_form).and_return(remote_response)
delete :destroy, ...
response.should whatever
(我假设您在控制器规范中,并且您将需要RSpec提供的response
对象,因此您的模拟不能存储在名为response
的变量中。
但这只是掩盖了更重要的一点,即您应该将远程服务交互提取到专用类中并单独测试,它不属于控制器。
希望有所帮助!