次のような型ヒントを使用する関数を含むクラスがあるとします。
class Testable
{
function foo (Dependency $dependency)
{
}
}
そして、私はこのコードを使用してこのクラスTestable
をユニットテストしたいと思います:
$dependencyMock = $this->getMockBuilder('Dependency')
->disableOriginalConstructor()
->getMock();
$testable = new Testable($dependencyMock);
PHPUnitを使用して$ dependencyのスタブを作成し、このモック(上記のように)を使用してfoo
関数を呼び出そうとすると、次のような致命的なエラーが発生します。
関数foo()に渡される引数1はDependencyのインスタンスでなければならず、Mock_Fooのインスタンスが指定されている必要があります
この関数をPHPUnitで単体テストし、$dependency
をスタブするにはどうすればよいですか?
モックを使用する場合は完全な名前空間を使用してください。これにより、モカリー継承の問題が修正されます。
$dependencyMock = $this->getMockBuilder('\Some\Name\Space\Dependency')
->disableOriginalConstructor()
->getMock();
$testable = new Testable($dependencyMock);
PHP 5.4+で完全な名前空間を使用する最も簡単な方法は、クラスの静的メソッドを使用することです。
SomeClass::class
OPの例では:
$dependencyMock = $this->getMockBuilder(Dependency::class)
->disableOriginalConstructor()
->getMock();
$testable = new Testable($dependencyMock);
これにより、IDEを使用したリファクタリングがはるかに簡単になります
シャキルの答えの私の説明:
私も同じ問題を抱えていました。
Symfony2クックブックに従って、私はのモックを作成しました
\Doctrine\Common\Persistence\ObjectManager
そして私のサービスコンストラクタは:
use Doctrine\ORM\EntityManager;
/* ... */
public function __construct(EntityManager $oEm)
{
$this->oEm = $oEm;
}
だから私はユニットテストを作成しました(symfony2クックブックに従って):
$entityManager = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')
->disableOriginalConstructor()
->getMock();
$myService = new MyService($entityManager);
次に、エラーが発生しました:
Argument 1 passed to MyService::__construct() must be an instance of Doctrine\ORM\EntityManager, instance of Mock_ObjectManager_f4068b7f given
EntityManagerのインスタンスではなくモックインスタンスがコンストラクターに渡されたため、最初にその型ヒントは単体テストと互換性がありませんでした。
したがって、いくつかの調査の後、クラスMock_ObjectManager_f4068b7fは実際にはモックのクラスを拡張する動的クラス(私の場合はDoctrine\ORM\EntityManager)なので、型のヒントは問題ではなく、うまく機能します。
私の解決策は、\ Doctrine\Common\Persistence\ObjectManagerの代わりにDoctrine\ORM\EntityManagerのモックを作成することでした:
$entityManager = $this->getMockBuilder('\Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$myService = new MyService($entityManager);
私はユニットテストから始めているので、私の説明が明らかになるかもしれません:p