在 rspec 3.1.0 中,规范可以使用 #allow 存根方法:
describe do
specify do
o = Object.new
allow(o).to receive(:foo)
o.foo
end
end
这工作正常。但是,如果存根位于类的方法中,则不定义 #allow 方法:
describe do
class Baz
def allow_bar(o)
allow(o).to receive(:bar)
end
end
specify do
o = Object.new
Baz.new.allow_bar(o)
o.bar
end
end
错误是:
Failure/Error: allow(o).to receive(:bar)
NoMethodError:
undefined method `allow' for #<Baz:0x8de6720>
# ./bar_spec.rb:5:in `allow_bar'
# ./bar_spec.rb:11:in `block (2 levels) in <top (required)>'
为什么我在课堂上存根
该测试将其测试替身定义为常规类,而不是使用 rspec 的“double”方法。这是因为测试替身有一个线程。测试替身里面是这段代码:
if command == :close
# Note: Uses the old (rspec 2) syntax. Needs to be converted
# to rspec 3 syntax using the #allow method.
socket.stub(:getpeername).and_raise(RuntimeError, "Socket closed")
end
这可以防止被测代码在会话关闭后错误地使用套接字。
私人解决方案
我可以通过在 rspec-mock 中调用私有 API 来为测试提供对 #allow 的双重访问权限:
class Baz
RSpec::Mocks::Syntax.enable_expect self # Uses private API
def allow_bar(o)
allow(o).to receive(:bar)
end
end
这行得通。但是,它在 rspec/mocks/syntax.rb 中被明确标记为私有 API:
# @api private
# Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc).
def self.enable_expect(syntax_host = ::RSpec::Mocks::ExampleMethods)
...
问题
在 Rspec 3.1 中,我是否可以使用公共API 来使期望语法在类中可用?