【问题标题】:RSpec sequence of returned values AND raised errors from stub返回值的 RSpec 序列并从存根引发错误
【发布时间】:2016-06-03 08:04:44
【问题描述】:

我想存根对 HTTParty 的前两次调用并引发异常,然后第三次调用应该返回值。

   before do
          allow(HTTParty).to receive(:get).exactly(2).times.with(url).and_raise(HTTParty::Error)
          allow(HTTParty).to receive(:get).with(url).and_return('{}')
        end

但是一个允许覆盖另一个。如何设置存根在前几次尝试中引发错误,然后让它返回一个值?

【问题讨论】:

标签: ruby-on-rails ruby testing rspec rspec3


【解决方案1】:

根据this github issue 中提供的信息,您也可以使用以下纯 RSpec 方法来做到这一点。它利用了定义模拟响应using block的最通用方法:

before do
  reponse_values = [:raise, :raise, '{}']
  allow(HTTParty).to receive(:get).exactly(3).times.with(url) do
    v = response_values.shift
    v == :raise ? raise(HTTParty::Error) : v
  end
end

【讨论】:

  • 不错!如果你设置了reponse_values = [nil, nil, '{}'],你可以使用来自 GitHub 问题的简洁的response_values.shift || raise(HTTParty::Error) 技巧。
  • 没错!虽然在这种情况下我更喜欢“明确性”。
【解决方案2】:

在这种特定情况下,您可以使用 WebMock:

Multiple responses using chained to_return(), to_raise() or to_timeout declarations

这样的事情应该可以工作:

before do
  stub_request(:get, url).
    to_raise(SomeException).then.
    to_raise(SomeException).then.
    to_return(body: '{}')
end

SomeException 应该是实际的网络错误。

【讨论】:

    【解决方案3】:

    您可以使用Proc 实例数组来完全控制:

    my_object = double
    values = [proc { raise ArgumentError }, proc { 2 }]
    
    allow(my_object).to receive(:my_method).exactly(:twice) { values.shift.call }
    
    expect { my_object.my_method }.to raise_error ArgumentError
    expect(my_object.my_method).to eq 2
    

    这样,您可以在多个调用中引发不同的异常,或者只返回值以满足您的需求。

    当您的存根响应全部被使用后,您可以使用类似的方法调用原始响应:

    allow(my_object).to receive(:my_method).and_wrap_original do |original, *args|
      values.empty? ? original.call(*args) : values.shift.call
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 2021-09-03
      • 2013-02-03
      • 1970-01-01
      • 2011-08-22
      • 2021-11-14
      • 1970-01-01
      相关资源
      最近更新 更多