rspec 3.1.0 では、spec は #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" メソッドを使用するのではなく、そのテスト double を通常のクラスとして定義します。これは、テスト ダブルにスレッドがあるためです。test 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 では、expect 構文をクラス内で使用できるようにするために使用できるパブリックAPI はありますか?