確認

2012-02-28 6 views
13

確認

->with($this->equalTo('foobar')) 

または任意の

->with($this->anything()) 

パラメータの特定と呼ばれていました。

しかし、メソッドがパラメータなしで呼び出されたことを指定する方法はありますか?

この私が失敗することを期待テストです:

public function testZ() 
{ 
    $a = $this->getMock('q'); 

    $a->expects($this->once()) 
     ->method('z') 
     ->with(); // <--- what constraint to specify here? 

    $a->z(1); 
} 

UPD

質問は、理論的な性質を持っているので、私は任意の実際の生活の例何を持っていません。私は今考えることができますいくつかの場合、それは有用である可能性がある:(foo()を想定し、デフォルトのものを持っている)

public function testMe($object) 
{ 
    $object->foo(); 
} 

とのは、testMeは、(設計によっておよび要件によって)常にパラメータなしでメソッドを呼び出す必要があることを想定してみましょう。この場合、デフォルト以外のパラメータ(より正確には、すべてのパラメータ!=既定のパラメータ!=未知であり、おそらく独立して変更できる可能性があるため)は致命的な結果を招きます。

+0

+1 PHPUnitのソースをgithub上で調べてみたところ、 ' - > with()'のように見えるのは、実際にパラメータを指定して、禁止するのではなく、私は実際には引数が渡​​されていないことを確認するシナリオを考えることができますが、あなたがチェックする必要があるものですか?なぜ引数が送られなかったのかを確認する必要があるのか​​どうか聞くことに興味があります。何も期待されていないときに引数を渡すと何も壊れませんし、提供できない引数がある場合にはNULLを渡すことはできませんか? – rdlowrey

+0

@rdlowrey:説明の更新を追加しました;-) – zerkms

+0

@rdlowrey: '提供できないと予想される引数があるときにNULLを渡すことはできませんか?'できません。メソッドはまだオプションのパラメータを持つことができます – zerkms

答えて

6

with()は引数が渡​​されていないかどうかをチェックする手段を用意していませんが、問題はPHPUnitではなくPHP自身にあります。

まず、メソッドにデフォルト値が指定されていない場合、パラメータを渡さないと、インタープリタは致命的なエラーを発生させます。これは、当面の疑問に完全に関連するものではないと予想されていますが、正面から考えることが重要です。

の場合、引数を指定しないでメソッドを呼び出すと、PHPUnitがデフォルト値を渡す前にPHPが呼び出しを変更します。 PHPがパラメータを確認する前に、PHP自体を挿入する方法を示す簡単なテストです。 PHPが作成するモッククラスは、モックされたクラスと同じシグネチャ(既定値を含む)を持つことに気付くことが重要です。

class MockTest extends PHPUnit_Framework_TestCase { 
     public function test() { 
       $mock = $this->getMock('Foo', array('bar')); 
       $mock->expects($this->once()) 
        ->method('bar') 
        ->with() // does nothing, but it doesn't matter 
        ->will($this->returnArgument(0)); 
       self::assertEquals('foobar', $mock->bar()); // PHP inserts 1 and 2 
       // assertion fails because 1 != 'foobar' 
     } 
} 

class Foo { 
     public function bar($x = 1, $y = 2) { 
       return $x + $y; 
     } 
} 

は、これはあなたが何もどちらかが渡されなかったか、デフォルト値が渡されたことを確認できることを意味しますが、あなたは、より具体的にすることはできません。

この制限を回避できますか?メソッドをオーバーライドするときには、引数からデフォルト値を削除することができるので、サブクラスを作成してモックすることができます。その価値はありますか?私の最初の腸の反応は、これは巨大なコードの匂いであるということです。あなたのデザインやテストが間違ったこと(tm)をしています。

この種のテストを実際に行う必要がある現実的で具体的な例を提供することができれば、解決策を考えるのに時間を費やす価値があります。それまでは、私は純粋に学問的な答えである「しないでください」に満足しています。 :)

+0

+1。私はそれがコードの臭いのように見えることに同意します...私は実際のアプリケーションを見ていない、単純なリファクタリングが回避する問題のように思えます。 – rdlowrey

+0

"それまでは、私は純粋に学問的な答えである"それをしないでください "と満足しています:)" ---私は実世界の例を考えることができないと私は同意します。なぜ理論が必要なのかを説明せずにそのことを理論的に尋ねたところです。 – zerkms

+0

しかし、まだ嘲笑はどういうことかと思っています。 – zerkms

4

PHPUnitモックオブジェクトでは、->with()制約メソッドを使用して、渡されたパラメータの数またはそれぞれの値が呼び出されたときに模擬メソッドに渡された値と一致することを確認できます。 引数なしが模擬メソッドに渡されることを要求するために使用することはできません。

模擬検証プロセスは、渡されたパラメータ数と関連する値がwith制約に渡された値と互換性があるかどうかを特にチェックします。また、おそらく見てきたように、値を指定せずにwithの制約を指定しても動作しません。 withにパラメータが指定されていない場合、検証のためのパラメータ制約は追加されません。

実際のPHPUnit_Framework_MockObject_Matcher_Parameters::verifyメソッドを使用して、リンクされたgithubソースのモックメソッドパラメータを確認することができます。

引数が渡されていないことを検証する必要がある場合は、PHPUnitモッキング機能以外の条件を検証するために、独自のモッククラスを指定する必要があります。

+0

この回答を編集せずに、PHPUnitの内部についての不可解な微妙な理解からではなく、問題の述べられた目標を達成するために関連するソースコードを探していることから、この結論に至りました。私はリンクされたソースコードは不可能だという証拠だと思いますが、誰かがそれを動作させる方法を見つけ出すことができれば、分かち合いましょう。明確化のために+1 – rdlowrey