web-dev-qa-db-ja.com

メソッドをモックしないでphpunitにモックを作成しますか?

PHPUnitを使用してphpコードをユニットテストしているとき、オブジェクトのメソッドをモックせずにオブジェクトをモックする正しい方法を見つけようとしています。

問題は、getMockBuilder()->setMethods()を呼び出さないと、オブジェクトのすべてのメソッドがモックされ、テストするメソッドを呼び出せないことです。しかし、私がdoを呼び出してsetMethods()を呼び出すと、どのメソッドをモックするかを伝える必要がありますが、メソッドをまったくモックしたくありません。しかし、テストでコンストラクターを呼び出さないように、モックを作成する必要があります。

テストしたいメソッドの簡単な例を次に示します。

_class Foobar
{
    public function __construct()
    {
        // stuff happens here ...
    }

    public function myMethod($s)
    {
        // I want to test this
        return (strlen($s) > 3);
    }
}
_

私はmyMethod()を次のようにテストするかもしれません:

_$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));
_

しかし、これはFoobarのコンストラクターを呼び出します。だから代わりに私は試してみます:

_$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));
_

ただし、getMockBuilder()を使用せずにsetMethods()を呼び出すと、そのすべてのメソッドがモックされてnullが返されるため、myMethod()を呼び出すと、コードに触れずにnullが返されます。テストするつもりです。

これまでの私の回避策はこれです:

_$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
    ->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));
_

これは存在しない 'none'という名前のメソッドをモックしますが、PHPUnitは気にしません。 myMethod()のモックが解除された状態で呼び出せるようになるだけでなく、コンストラクターを無効にして呼び出せないようにすることもできます。パーフェクト!存在しないメソッド名を指定する必要があるのはごまかしのようです-'none'、 'blargh'、または 'xyzzy'。

これを行うための正しい方法は何でしょうか?

37
Brian Kendig

メソッドのモックを避けるためにnullsetMethods()に渡すことができます。空の配列を渡すと、すべてのメソッドがモックされます。後者は、ご存じのとおりメソッドのデフォルト値です。

そうは言っても、これを行う必要性は、このクラスの設計の欠陥を指摘するかもしれないと私は言うでしょう。このメソッドを静的にするか、別のクラスに移動する必要がありますか?メソッドが完全に構築されたインスタンスを必要としない場合、それは静的にできるユーティリティメソッドである可能性があるというサインです。

47
David Harkness

もう1つのハックですが簡潔な解決策は、マジックコンストラクターをモックされたメソッドの1つとしてリストすることです。

$mock = $this->getMock('MyClass', array('__construct'));
3
Mike Petrovich

または、getMock()を直接使用することもできます。

$mock = $this->getMock('MyClass', null, array(), null, false);

0
Ryan

ケースでは、任意の方法、例えば。これは、entityManagerを介して呼び出され、これを使用できる場合があります。

$this->entityManager
        ->expects($this->any())
        ->method($this->anything())
        ->willReturn($repository);
0
urlichsanais