有没有办法创建一个Doctrine 2实体管理器的模拟器,并在Symfony 2 PHPUnit测试中为它提供一个模拟实体?

时间:2014-06-25 18:32:55

标签: php symfony doctrine-orm phpunit

我的任务是为遗留代码编写单元测试。我当前的测试是在一个对象上,它将Doctrine 2实体管理器作为构造函数参数。我需要能够提供测试数据,以便我可以可靠地测试其方法。

所以,理想情况下,我希望能够创建一个模拟实体管理器,然后创建一个模拟实体并将其附加到模拟实体管理器,然后在我的测试中使用它。这可能吗?如果是这样,怎么样?

这个项目正在使用Symfony 2.4+,所以我很确定在设置中增加了一两个皱纹。

1 个答案:

答案 0 :(得分:17)

不确定这是否适用于您在Symfony(完整堆栈?)设置中的特定需求,但是在我们之前使用Symfony Components(和Doctrine)的项目中,但不是全栈,这更多或是减少设置:

<?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()
        );
    }
}