0

如果参数是一种异常,我想扩展and_return方法以引发异常。例如

obj.stub(:meth).and_return(SomeException,"message")

这种构造应该在第一次调用时引发异常,并在第二次调用时返回字符串。

如何通过这种方法扩展 rspec,是否有此类任务的指南?

更新:

此函数的一般表示法可以是:

and_return_or_raise(list of arguments or/and exceptions)
4

3 回答 3

1

怎么样

stuff = [SomeException, "message"]
obj.stub(:meth).and_return do
  i = stuff.shift
  if i.respond_to?(:downcase)
    i
  else
    raise i
  end
end    

当然不是最漂亮的方式,但应该在您的特定情况下完成这项工作。

于 2013-01-08T15:24:37.007 回答
1

所以,返回多个值的实际业务是在类中的这个方法RSpec::Mocks::MessageExpectation

def call_implementation_consecutive(*args, &block)
  @value ||= call_implementation(*args, &block)
  @value[[@actual_received_count, @value.size-1].min]
end

基本上,call_implementation返回您传递给的预期返回值列表and_return,并且此方法挑选出与当前调用相对应的那个(如果我们调用该方法的次数多于列表中的值,则返回最后一个值)。

所以,要做你想做的事,你可以猴子修补这个方法,如下所示:

class RSpec::Mocks::MessageExpectation
  alias_method :old_call_implementation_consecutive, :call_implementation_consecutive

  def call_implementation_consecutive(*args, &block)
    old_call_implementation_consecutive(*args, &block).tap do |value|
      raise value if value.is_a?(Class) && value < Exception
    end
  end
end
于 2013-01-08T17:20:39.760 回答
1

你不需要扩展任何东西——只需使用 RSpec 的内置错误匹配器并接收计数:

class Foobar
  def foo
    bar
  end
end

it "raises the first time, then returns a string" do
  obj = Foobar.new
  obj.should_receive(:bar).once.and_raise(StandardError)
  obj.should_receive(:bar).once.and_return("message")
  expect { obj.foo }.to raise_error(StandardError)
  obj.foo.should == "message"
end
于 2013-01-08T17:23:40.883 回答