ruby-on-rails RSpec返回值序列AND从存根引发错误

iszxjhcz  于 2023-01-03  发布在  Ruby
关注(0)|答案(4)|浏览(117)

我想stub前两个对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

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

a64a0gku

a64a0gku1#

根据本期github提供的信息,你也可以使用下面的纯RSpec方法来实现,它利用了使用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
lf5gs5x2

lf5gs5x22#

在这种特定情况下,您可以使用WebMock:
使用链式to_return()to_raise()to_timeout声明的多个响应。
类似这样的方法应该可以奏效:

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

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

des4xlb0

des4xlb03#

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

5m1hhzi44#

我喜欢@b-f方法,但是用#and_invoke简化了它,而且我已经指定了返回值,所以我只需要知道它们都被使用了。

allow(my_object).to receive(:my_method).and_invoke(proc { raise ArgumentError }, proc { 2 } )
expect(my_object).to have_received(:my_method).exactly(2).times

相关问题