How to unit test functions that use type hinting

Solution 1:

Use full namespace when you use mocking, it will fix the mockery inheritance problem.

$dependencyMock = $this->getMockBuilder('\Some\Name\Space\Dependency')
    ->disableOriginalConstructor()
    ->getMock();
$testable = new Testable($dependencyMock);

Solution 2:

The easiest way to use a full namespace in PHP 5.4+ is with the class static method:

SomeClass::class

So in the OP's example:

$dependencyMock = $this->getMockBuilder(Dependency::class)
    ->disableOriginalConstructor()
    ->getMock();
$testable = new Testable($dependencyMock);

This makes refactoring with an IDE a lot easier

Solution 3:

My explication for the Shakil's answer:

I had the same problem.

Following the symfony2 cookbook, I created a mock of

\Doctrine\Common\Persistence\ObjectManager

and my service constructor was:

use Doctrine\ORM\EntityManager;

/* ... */

public function __construct(EntityManager $oEm)
{
    $this->oEm = $oEm;
}

So I created my unit test (following symfony2 cookbook):

$entityManager = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')
    ->disableOriginalConstructor()
    ->getMock();

$myService = new MyService($entityManager);

Then I had the error:

Argument 1 passed to MyService::__construct() must be an instance of Doctrine\ORM\EntityManager, instance of Mock_ObjectManager_f4068b7f given

First I though that type hinting was incompatible with unit tests, because a mock instance was passed to the constructor instead of an instance of EntityManager.

So after some research, the class Mock_ObjectManager_f4068b7f is in fact a dynamic class extending the class of your mock (in my case Doctrine\ORM\EntityManager), so the type hinting is not a problem and works well.

My solution was to create a mock of Doctrine\ORM\EntityManager instead of \Doctrine\Common\Persistence\ObjectManager:

$entityManager = $this->getMockBuilder('\Doctrine\ORM\EntityManager')
    ->disableOriginalConstructor()
    ->getMock();

$myService = new MyService($entityManager);

I am just beginning with unit tests, so you may find my explication evident :p