返回值的RSpec序列和存根中引发的错误

时间:2016-06-03 08:04:45

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

我希望将前两次调用带有引发异常的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

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

3 个答案:

答案 0 :(得分:6)

根据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

答案 1 :(得分:1)

在这种特定情况下,您可以使用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应该是实际的网络错误。

答案 2 :(得分:0)

您可以使用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