デメテルチェーンとfluentインターフェイスのモック
両語ともに以下のような形態の、よく使われるようになってきたメソッド起動の実働コードを意味します。
$object->foo()->bar()->zebra()->alpha()->selfDestruct();
呼び出し側のクラスが知っているローカルオブジェクトへ、それぞれのリンクが戻っていると仮定すれば、メソッド呼び出しの長いチェーンは悪いとは言い切れません。面白い一例は、(最初のshouldReceive()
メソッドに続く)Mockeryの長いチェーンは、すべて同じ\Mockery\Expectation
インスタンスを呼び出しています。しかしながら、時々これが当てはまらずに、チェーンがオブジェクトの境界をまたぐことがあります。
どちらの場合でも、このようなチェーンをモックするのはひどい仕事になり得ます。簡単にするために、Mockeryはデメテルチェーンのモックをサポートしています。簡潔に言えば、チェーン全体のショートカット記法と、最後の呼び出しの戻り値の定義です。例として、selfDestruct()
メソッドが、文字列の"Ten!"を(CaptainsConsole
のインスタンスの)オブジェクトへ返すと仮定してみましょう。これをモックする例をご覧ください。
$mock = \Mockery::mock('CaptainsConsole');
$mock->shouldReceive('foo->bar->zebra->alpha->selfDestruct')->andReturn('Ten!');
上記のエクスペクションは、前記のチェーンの形式に従っています。例外はチェーンで呼び出される全てのメソッド名が、->
で分割されたシンプルな文字列になっていることです。実際の実装がチェーン間でどんなオブジェクトを使用しているかに関係なく、Mockeryは自動的に、チェーン呼び出しの期待と、最終的な返り値を設定します。
この過程で、チェーンの全ての要素の引数は(最後の呼び出しを除き)、無視されます。