如何检查在另一个方法 rspec 中调用的方法的返回值?

问题描述

假设你有一些类似的课程

class Foo
  ...
  public def methodA
    x = methodB(true)
    # other operations (assume x is not the return value of methodA)
  end

  private def methodB(arg)
    if arg
      return 1
    else
      return 0
    end
  end
end

当您为 methodA 编写单元测试时,您想检查 x 是否被分配了正确的值,这意味着您必须检查对 methodB调用是否返回1 如您所料。

您将如何在 rspec 中进行测试?

现在我有(在 How to test if method is called in RSpec but do not override the return value 的帮助下)

@foo = Foo.new
expect(@foo).to receive(:methodB).with(true).and_call_original

但是我不知道如何验证methodB的实际返回值。

解决方法

我认为您可以调用私有方法而不是嘲笑?

@foo = Foo.new
result = foo.send(:methodB,true)
expect(result).to eq 1

这基本上是直接测试私有方法。有些人不喜欢这样做,但如果它有很多逻辑,有时直接测试它会更容易。我同意@spickermann 的观点,通常最好测试公共方法并将私有方法的实现细节排除在规范之外。

,

不要在一个单元测试中测试多种方法

您这样做是错误的,因为您在两种不同的方法之间创建了不必要的依赖关系。相反,您应该重构您的代码,以便:

  1. x 是 #methodA 的参数,
  2. x@x@@x 是一个可供 methodA 访问的变量,您可以将其设置为您想要的任何期望值,或
  3. 为这个单元测试剔除#methodB。

作为最后一个例子:

describe Foo do
  describe 'methodA' do
    it 'does something when methodB returns 1' do
      # stub the default subject,which is Foo.new
      allow(subject).to receive(:methodB) { 1 }
      expect(subject.methodA).to eq('foo bar baz')
    end
  end
end

此代码未经测试,因为您发布的代码不是完整的、可验证的示例。虽然您最好重构您的代码,这样您根本就不会测试嵌套的依赖项,但使用 test doubles or method stubs 当然是可行的选择。