我想模拟一个可能收到任何我不关心的消息的对象。我希望这个对象有一个默认的答案,比如'true',能够添加特定的方法和答案。是否可以在RSpec中执行此操作?我想要的是这样的:
obj = default_double(default: true, widget_count: 5)
obj.foobar.should == true
obj.widget_count.should == 5
如果我可以传入一个lambda或proc作为返回值并让default_double返回该lambda的评估,那就太好了。如果在测试的上下文中评估proc或lambda,并且可以访问示例中可用的变量,那将是非常好的。
因此,如果添加了上述功能,我们可能会有类似的内容:
@widgets = WidgetContainer.new
@widgets.widget_count = 5
obj = default_double(default: true, widget_count: lambda { @widgets.widget_count })
obj.foobar.should == true
obj.widget_count.should == 5
如果这个功能的动机对读者来说很有意思,那么让我们假设我不想挖掘并找出它可能收到的所有可能的消息,或者可能的消息集非常大或未知。 / p>
RSpec内置了这样的内容吗?
答案 0 :(得分:0)
好的,我会小心翼翼地回答这个问题:
我相信RSpec 不具有内置的模拟功能,它将接收任意消息并返回默认值。但是,它允许您将返回值指定为块,与Ruby的method_missing
功能一起,应该允许您相当容易地构造上面描述的default_double
方法。
虽然它可以从一些重构中获益,但是通过上面的例子,这是一个切入点:
require 'spec_helper'
def default_double(args)
object = Object.new
args.each do |key, value|
if key == :default
object.define_singleton_method(:method_missing) { |method, *args, &block| value }
elsif Proc === value
expect(object).to receive(key) do value.call end
else expect(object).to receive(key).and_return(value)
end
end
object
end
class WidgetContainer
attr_accessor :widget_count
end
describe "default_double test" do
it "should pass" do
@widgets = WidgetContainer.new
@widgets.widget_count = 5
obj = default_double(default: true, widget_count: lambda { @widgets.widget_count })
obj.foobar.should == true
obj.widget_count.should == 5
end
end