How to mock dependency injection with phpunit?

mocking, phpunit, symfony

Solution

You have to use the real classname, otherwise PHPunit will just create a class named `Router` (note: this is not the expected `Symfony\Component\Routing\Router`):

     // don't need it here, Swift_Mailer is in the global scope
    $mailer = $this->getMockBuilder('Swift_Mailer')
        ->disableOriginalConstructor()
        ->getMock();

    $router = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\Router')
        ->disableOriginalConstructor()
        ->getMock();

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

    $emailMan = $this->getMockBuilder('Full\Namespace\To\EmailManager')
        ->disableOriginalConstructor()
        ->getMock();

    $emailReminderMan = $this->getMockBuilder('Full\Namespace\To\EmailReminderManager')
        ->disableOriginalConstructor()
        ->getMock();

Problem

I wish to test methods in this class: ``` class EmailerService { protected $mailer; protected $router; protected $em; protected $emailMan; protected $emailReminderMan; protected $secret; /** * Construct * * @param \Swift_Mailer $mailer * @param \Symfony\Bundle\FrameworkBundle\Routing\Router $router * @param \Doctrine\ORM\EntityManager $em * @param EmailManager $emailMan * @param EmailReminderManager $emailReminderMan * @param $secret */ public function __construct(Swift_Mailer $mailer, Router $router, EntityManager $em, EmailManager $emailMan, EmailReminderManager $emailReminderMan, $secret) { $this->mailer = $mailer; $this->router = $router; $this->em = $em; $this->emailMan = $emailMan; $this->emailReminderMan = $emailReminderMan; $this->secret = $secret; } ``` My test currently looks like this: ``` class EmailerServiceTest extends \PHPUnit_Framework_TestCase { protected $emailer; public function setUp() { $mailer = $this->getMockBuilder('Swift_Mailer') ->disableOriginalConstructor() ->getMock(); $router = $this->getMockBuilder('Router') ->disableOriginalConstructor() ->getMock(); $em = $this->getMockBuilder('EntityManager') ->disableOriginalConstructor() ->getMock(); $emailMan = $this->getMockBuilder('EmailManager') ->disableOriginalConstructor() ->getMock(); $emailReminderMan = $this->getMockBuilder('EmailReminderManager') ->disableOriginalConstructor() ->getMock(); $secret = '123'; $this->emailer = new EmailerService($mailer, $router, $em, $emailMan, $emailReminderMan, $secret); } ``` But I get the error: 1) T\CBundle\Tests\Service\EmailerServiceTest::testGetVariablesForModule Argument 2 passed to T\CBundle\Service\EmailerService::__construct() must be an instance of Symfony\Bundle\FrameworkBundle\Routing\Router, instance of Mock_Router_3e61717e given, called in ... Also a bit confused why it triggers with Router, and not first with Swift_Mailer

Original source