如何将it_behaves_like中带有存根方法的对象传递给rspec中的shared_examples_for块?

时间:2014-01-03 08:06:11

标签: rspec

我有一个类似

的规范
describe MyClass do
  it_behaves_like SharedClass, MyClass.new
end

在我的共享示例规范中,我有

shared_examples_for SharedClass do |instance|
  before do 
    instance.some_my_class_method = double
  end
  # some specs here
end

MyClass实例中的方法很少,我不能在shared_examples_for块中存根,所以我想在it_behaves_like语句中传递它们之前将它们存根。等,

describe MyClass do
  before do
    @instance = MyClass.new
    @instance.stub(:my_class_method)
  end
  it_behaves_like SharedClass, @instance
end
但是我不能这样做。它会把我扔掉 NoMethodError:        未定义的方法`some_my_class_method ='为nil:NilClass

不知怎的,我无法在shared_examples_for上下文中访问该@instance对象。 我使用的是ruby 1.9.3p392和rspec(2.14.1)

1 个答案:

答案 0 :(得分:2)

问题是传递给it_behaves_like的参数是在调用it_behaves_like时计算的,而before块是在执行共享示例之前计算的,这会发生晚些时候。因此,@instance作为参数评估为nil,形式参数instance被指定为nil,从而导致undefined method错误。

我不知道有什么简单的方法来做你想要完成的事情。 this documentation中显示的一个替代方法是消除形式参数并要求调用者传递一个块,该块使用let来建立参数值,使用一些同意的变量,如下所示:

describe MyClass do
  it_behaves_like SharedClass {let(:instance) { MyClass.new }}
end

describe MyClass do
  it_behaves_like SharedClass do
    let(:instance) do
      myClass = MyClass.new
      myClass.stub(:my_class_method)
      myClass
    end
  end
end

然而,除了更详细之外,这还有一个缺点,即共享示例中没有隐含的文档,它希望instance在调用它时设置。

虽然我没有看到它在任何地方讨论过,但是当有并且只有当形参数的值为nil时,你的共享示例才会使用块中的约定变量。这可能是为了方便而违约的。不幸的是,你不能为两者使用相同的变量,因为参数的值总是优先。