使用 Rspec 监视实例方法

Bri*_*cle 2 ruby rspec

我有一堂有多种方法的课程,例如

class MyClass
  def method_a(p)
    method_b if p == 1
  end

  def method_b
    some_more_stuff
  end
end
Run Code Online (Sandbox Code Playgroud)

我希望使用 RSpec 来测试method_a(有时)调用method_b.

it 'calls method_b if the passed parameter is 1' do
  instance = spy('MyClass')

  instance.method_a(1)

  expect(instance).to have_received(:method_b)
end
Run Code Online (Sandbox Code Playgroud)

不幸的是,因为 RSpec 间谍不会将方法调用传递给他们正在监视的对象,所以spy.method_a实际上不会调用spy.method_b. 我尝试过使用双打和实例双打,但现在非常困惑。

如何让 RSpec double 或间谍或其他实例对象观察实例的内部方法调用而不完全替换它们?我愿意method_b以某种方式进行嘲笑,但也不知道如何正确地做到这一点。

小智 5

Generally I don't recommend testing things like this way, since method call is a completely internal thing. Remember, RSpec is BDD framework, and BDD is not about internal things.

However, I understand sometimes we want to test internal things using mocks and stubs. So, here's an example code:

RSpec.describe MyClass do
  it 'calls method_b if the passed parameter is 1' do
    instance = MyClass.new
    expect(instance).to receive(:method_a).and_call_original
    expect(instance).to receive(:method_b)

    instance.method_a(1)
  end
end
Run Code Online (Sandbox Code Playgroud)

The key part is that we actually instantiate MyClass so that we can use and_call_original method only available on partial test doubles.