Question

Lets say I have a class that contains a function that uses type hinting like this:

class Testable 
{
    function foo (Dependency $dependency) 
    {

    }
}

And I want to unit test this class Testable using this code:

$dependencyMock = $this->getMockBuilder('Dependency')
        ->disableOriginalConstructor()
        ->getMock();


$testable = new Testable($dependencyMock);

If I use PHPUnit to create a stub of $dependency and then try to call the function foo using this mock (like above), I will get a fatal error that says:

Argument 1 passed to function foo() must be an instance of Dependency, instance of Mock_Foo given

How can I unit test this function with PHPUnit and still stub $dependency?

Was it helpful?

Solution

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);

OTHER TIPS

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top