0

私は rspec を学んでいますが、他のメソッドのチェーンを呼び出すメソッドの仕様を記述する最も効果的な方法を考えています。例えば:

class Example1
  def foo(dependency)
     dependency.bar("A")
     dependency.baz("B")
     dependency.bzz("C")
  end
end

理想的には、次のような仕様を書きたいと思います。

it "should call bar" do
   ex = Example1.new
   dep = mock
   dep.should_receive(:bar).with("A")
   ex.foo(dep)
end
it "should call baz"
   ... 
it "should call bzz"
   ...

ただし、これを行うと、(当然のことながら)「予期しないメソッド呼び出し baz」などの例外が発生します。

それで、それに対処する最善の方法は何ですか?私はいくつかのアイデアを思いつきましたが、どれが良いかわかりません。

  1. モックの依存関係を「as_null_object」にして、余分な呼び出しを無視します。(マイナス面-そのオブジェクトで不要なランダムなものを呼び出していた場合、私はそれを知りません)
  2. 各仕様で使用されていない 2 つの依存関係メソッド呼び出しをスタブ化します (欠点 - 非常に DRY に感じます)
  3. 3 つすべての依存関係呼び出しを「前」にスタブします (欠点 - 「前」に多くのがらくたを置きます)
4

3 に答える 3

1

RSpec には stub_chain と呼ばれる機能があります: https://www.relishapp.com/rspec/rspec-mocks/v/2-0/docs/stubs/stub-a-chain-of-methods

それらすべてを 1 つの例でテストするのはどうでしょうか。

it "should call bar"
   ex = Example1.new
   dep = mock
   dep.should_receive("bar").with("A")
   dep.should_receive("baz").with("B")
   dep.should_receive("bzz").with("C")
   ex.foo(dep)
end

それが重要な場合は、RSpec を使用してそれらが呼び出される順序を確認できると思います。

ただし、この種のアプローチは、多くの場合、コードの記述方法に問題があることを示しています (デメテルの法則違反など)。あなたの例でfooは、依存関係のクラスのメソッドである必要があります。

于 2013-03-31T14:26:56.370 に答える
1

RSpec が提供するオプションについては、すでに解決済みのようです。オプション 1 を使用し、 を使用しますas_null_object。そのオブジェクトに対する他のランダムなメソッド呼び出しが欠落している可能性があるのは事実ですが、これらの各テストのポイントが特定のメソッドが呼び出されていることを単にアサートすることである場合、特に高レベルの統合テストをカバーしている場合は問題ありません。この方法。

他のメソッドが呼び出されていないことを本当に確認する必要がある場合はdependency、オプション 3 が理にかなっていますが、実装が変更されると、そのようなテストは脆弱になる可能性があります。

余談ですが、テストを少し簡単にするsubjectために、明示的なインスタンス化を避けるために使用できます (ブロックExample1を使用していると仮定します)。describe Example1

subject.foo(dep)

(ただし、コメントの議論を参照してください - 暗黙の主語は意図を隠すことができます)。

于 2013-03-31T14:30:12.143 に答える