Ruby 如何扩展rspec模拟期望?
我想扩展Ruby 如何扩展rspec模拟期望?,ruby,rspec,Ruby,Rspec,我想扩展和_return方法,以在参数属于异常类型时引发异常。 比如说 obj.stub(:meth).and_return(SomeException,"message") 这种构造应该在第一次调用时引发异常,在第二次调用时只返回字符串 如何用这种方法扩展rspec,是否有针对此类任务的指南 更新: 此函数的一般符号可以是: and_return_or_raise(list of arguments or/and exceptions) 怎么样 stuff = [SomeException
和_return
方法,以在参数属于异常类型时引发异常。
比如说
obj.stub(:meth).and_return(SomeException,"message")
这种构造应该在第一次调用时引发异常,在第二次调用时只返回字符串
如何用这种方法扩展rspec,是否有针对此类任务的指南
更新:
此函数的一般符号可以是:
and_return_or_raise(list of arguments or/and exceptions)
怎么样
stuff = [SomeException, "message"]
obj.stub(:meth).and_return do
i = stuff.shift
if i.respond_to?(:downcase)
i
else
raise i
end
end
当然不是最漂亮的方式,但在你的特殊情况下应该能做到这一点。怎么样
stuff = [SomeException, "message"]
obj.stub(:meth).and_return do
i = stuff.shift
if i.respond_to?(:downcase)
i
else
raise i
end
end
当然不是最漂亮的方式,但应该在您的特定情况下完成这项工作。因此,返回多个值的实际业务是在
RSpec::Mocks::messageexpection
类中:
def call_implementation_consecutive(*args, &block)
@value ||= call_implementation(*args, &block)
@value[[@actual_received_count, @value.size-1].min]
end
基本上,call\u implementation
返回传递给和_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
class RSpec::Mocks::messageexpection
别名\u方法:旧的\u调用\u实现\u连续,:调用\u实现\u连续
def调用\实现\连续(*参数和块)
旧的_调用_实现_连续(*args,&block)。点击do |值|
如果值为(类)&&value<异常,则提升值
结束
结束
结束
因此,返回多个值的实际业务在RSpec::Mocks::messageexpection
类中:
def call_implementation_consecutive(*args, &block)
@value ||= call_implementation(*args, &block)
@value[[@actual_received_count, @value.size-1].min]
end
基本上,call\u implementation
返回传递给和_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
class RSpec::Mocks::messageexpection
别名\u方法:旧的\u调用\u实现\u连续,:调用\u实现\u连续
def调用\实现\连续(*参数和块)
旧的_调用_实现_连续(*args,&block)。点击do |值|
如果值为(类)&&value<异常,则提升值
结束
结束
结束
您不需要扩展任何内容——只需使用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
您不需要扩展任何内容——只需使用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
谢谢,它可以完成任务,但是让我们等待一个好的解决方案。谢谢,它可以完成任务,但是让我们等待一个好的解决方案。我指的是通用符号,所以我可以以任何顺序放置任何异常和参数。查看更新您可能可以使用自定义匹配器实现更通用的解决方案:我指的是通用表示法,因此我可以按任何顺序放置任何异常和参数。请参阅更新您可能可以使用自定义匹配器实现更通用的解决方案: