1

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 はありますか?

4

1 に答える 1

0

クラスにいくつかの RSpec モジュール/クラスを混在させることで、これを実現できます。

class MyClass
  include RSpec::Mocks::ExampleMethods::ExpectHost
  include RSpec::Matchers 

  def some_test
    expect(1).to eql(1)
  end
end
于 2015-04-29T18:23:48.617 に答える