【问题标题】:Getting 2 returns instead of 1 in tests在测试中获得 2 个回报而不是 1 个回报
【发布时间】:2012-11-21 08:51:20
【问题描述】:

我正在使用 double/stub 编写测试,我想返回一个假值,但我得到的是假值和真实值。这是我的控制器和规格文件,模型中没有任何内容。任何想法我做错了什么?我的猜测是我做错了。附:我对规范和模拟/存根有点陌生

控制器:

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

规格文件:

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"=>""}}

首先来自控制器 第二个来自存根

【问题讨论】:

    标签: ruby-on-rails ruby rspec mocking


    【解决方案1】:

    所以模拟和存根的问题是,你必须以某种方式将你的模拟对象连接到你的真实代码......double('http.request') 位只是创建一个名为“http.request”的模拟对象,它不会http.request返回这个对象。

    您需要做的是存根request 方法以返回模拟响应。但是注入 mock 将非常困难,因为您无法从测试中访问块中的 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 的变量中)。

    但这只是掩盖了更重要的一点,即您应该将远程服务交互提取到一个专用类中并单独测试,它不属于控制器。

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 2011-11-23
      • 1970-01-01
      • 2016-05-01
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 2021-09-25
      • 2018-07-15
      • 2014-12-01
      相关资源
      最近更新 更多