質問
保護されたメソッドがパブリックインターフェイスで呼び出されているかどうかをテストしようとしています。
<?php
abstract class SomeClassAbstract
{
abstract public foo();
public function doStuff()
{
$this->_protectedMethod();
}
protected function _protectedMethod();
{
// implementation is irrelevant
}
}
<?php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testCalled()
{
$mock = $this->getMockForAbstractClass('SomeClass');
$mock->expects($this->once())
->method('_protectedMethod');
$mock->doStuff();
}
}
正しく呼び出されていることはわかっていますが、PHPUnit は決して呼び出されないと言います。
メソッドが 一度もない 呼ばれる:
<?php
abstract class AnotherClassAbstract
{
abstract public foo();
public function doAnotherStuff()
{
$this->_loadCache();
}
protected function _loadCache();
{
// implementation is irrelevant
}
}
<?php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testCalled()
{
$mock = $this->getMockForAbstractClass('AnotherClass');
$mock->expects($this->once())
->method('_loadCache');
$mock->doAnotherStuff();
}
}
メソッドは呼び出されますが、PHPUnit は呼び出されないと通知します。
私の何が間違っているのでしょうか?
編集二重コロンを使用してメソッドを宣言しているのではなく、それがパブリック メソッド (インターフェイス) であることを示すためだけです。完全なクラス/メソッド宣言に更新されました。
編集2抽象クラスでいくつかのメソッド実装をテストしていると言うべきでした (これを反映するためにコードを編集しました)。クラスをインスタンス化できないため、これをテストするにはどうすればよいですか?
を作成しようと考えています SomeClassSimple
延長する SomeClassAbstract
代わりにこれをテストします。それは正しいアプローチですか?
解決
私が持っているPHPUnitのバージョンでは、クラス PHPUnit_Framework_MockObject_Mock
PHP を使用します get_class_methods
モックされるオブジェクトのインターフェイスを決定します。 get_class_methods
は、保護されたメソッドやプライベートなメソッドではなく、パブリックなメソッドのみを選択します。
これは、xUnit 単体テストの精神に沿ったものです。PHPUnit ドキュメントの使用例を検討してください。 モックオブジェクト. 。そこで、SUTは Subject
, 、保護されたメソッドがあります notify
. 。ただし、テストされているメソッドは、 doSomething
. 。検討中 Subject
ブラックボックスなので、実装方法の詳細は気にしません。ただし、私たちはそのことを気にしています 行動. 。具体的には、電話をかけるときにそれを要求します doSomething
, 、 そうして update
接続されているオブザーバーのメソッドが呼び出されます。したがって、サードパーティのオブジェクトをモックします Observer
, 、そして私たちはそれが update
メソッドが呼び出されます。protected メソッドですが、 notify
が実行されるが、テストでは明示的に名前が付けられません。これにより、動作が維持される限り、いつでも実装を自由に変更できるようになります。
例に戻ります。
class MyTest extends PHPUnit_Framework_TestCase
{
public function testCalled()
{
$mock = $this->getMock('SomeClass');
$mock->expects($this->once())
->method('_protectedMethod');
$mock->doStuff();
}
}
ほら、あなたの testCalled
このメソッドは、SomeClass となるテスト対象システム (SUT) のインスタンスを作成しません。のバージョン doStuff
の中に モック SomeClass は何もしません。特に呼びません _protectedMethod
.
他のヒント
単にその関数をモックアウトしたいことを PHPUnit に伝える必要があるようです。つまり、次のようになります。
$mock = $this->getMock('SomeClass',
array('_protectedMethod'));
$mock->expects($this->once())
->method('_protectedMethod');
$mock->doStuff();