【问题标题】:How to pass objects with stubbed methods in it_behaves_like to shared_examples_for block in rspec?如何将 it_behaves_like 中带有存根方法的对象传递给 rspec 中的 shared_examples_for 块?
【发布时间】:2014-01-03 08:06:11
【问题描述】:

我有一个类似的规格

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

但我不能那样做。它把我扔了
无方法错误: nil:NilClass 的未定义方法 `some_my_class_method='

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

【问题讨论】:

    标签: rspec


    【解决方案1】:

    问题是您传递给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 时,您共享的示例将使用块中的约定变量,这可以为方便起见默认。不幸的是,您不能对两者使用相同的变量,因为参数的值将始终优先。

    【讨论】:

    • 由于 let(:instance) 实际上定义了一个方法,因此您实际上可以为 let 使用与 shared_examples_for 参数(裸词)相同的名称。只需调用instance() 而不是裸词instance,它就会知道您指的是方法而不是局部变量...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 2017-07-29
    • 2023-03-29
    相关资源
    最近更新 更多