Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to create a mock of Doctrine 2's entity manager and supply it a mock entity in a Symfony 2 PHPUnit test?

I've been tasked with writing unit tests for legacy code. My current test is on an object that takes the Doctrine 2 entity manager as a constructor parameter. I need to be able to feed it test data so I can reliably test its methods.

So, ideally, I'd like to be able to create a mock entity manager, then create a mock entity and attach it to the mock entity manager, and then use that in my tests. Is this possible? If so, how?

This project is using Symfony 2.4+, so I'm pretty sure that adds a wrinkle or two in the setup.

like image 598
Major Productions Avatar asked Jun 25 '14 18:06

Major Productions


1 Answers

Not sure if this will apply or not to your specific needs in Symfony (full stack?) setup, but on previous projects where we were using Symfony Components (and Doctrine), but not the full-stack, this was more or less the setup followed:

<?php

namespace Tests\SomeNameSpace;

use Doctrine\ORM\EntityRepository;
use SomeNameSpace\Repositories\SomeRepository;
use SomeNameSpace\SubjectUnderTesting;

class SubjectUnderTestingTest extends \PHPUnit_Framework_TestCase
{

    public function testSomething()
    {
        $queryExpectedValue = 'define expected return from query';

        /**
         * Infering that the the Subject Under Test is dealing with a single
         * repository.
         *
         * @var Doctrine\ORM\EntityRepository
         */
        $repository = $this
            ->getMockBuilder('Doctrine\ORM\EntityRepository')
            ->disableOriginalConstructor()
            ->setMethods(array('findOneByEmail'))
            ->getMock();

        $repository
            ->expects($this->once())
            ->method('findOneByEmail')
            ->will($this->returnValue($queryExpectedValue));

        /**
         * Now mock the EntityManager that will return the aforementioned
         * Repository. Extend to more repositories with a returnValueMap or
         * with clauses in case you need to handle more than one repository.
         *
         * @var Doctrine\ORM\EntityManager
         */
        $entityManager = $this
            ->getMockBuilder('Doctrine\ORM\EntityManager')
            ->setMethods(array('getRepository'))
            ->disableOriginalConstructor()
            ->getMock();

        $entityManager
            ->expects($this->once())
            ->method('getRepository')
            ->with('SomeNameSpace\Repositories\SomeRepository')
            ->will($this->returnValue($repository));

        /**
         * Let's instantiate our Subject Under Test passing the mock as
         * required.
         *
         * This code above is tailored to a scenario where the SUT method
         * being tested will call something like this in the method to test:
         *
         * $queryResult = $entityManager
         *     ->getRepository('SomeNameSpace\Repositories\SomeRepository')
         *     ->findOneByEmail($someEmail);
         *
         * @var SubjectUnderTesting
         */
        $sut = new SubjectUnderTesting($entityManager);

        /**
         * Assertions time if they apply.
         */
        $expected = 'define what to expect';

        $this->assertEquals(
            $expected,
            $sut->callSomeMethodToTestThatDependsOnSomeQueryByEmail()
        );
    }
}
like image 176
ivanicus Avatar answered Oct 25 '22 15:10

ivanicus