【问题标题】: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?有没有办法创建一个 Doctrine 2 的实体管理器的模拟并在 Symfony 2 PHPUnit 测试中为其提供一个模拟实体?
【发布时间】:2014-08-16 10:49:11
【问题描述】:

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

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

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

【问题讨论】:

    标签: php symfony doctrine-orm phpunit


    【解决方案1】:

    不确定这是否适用于您在 Symfony(全栈?)设置中的特定需求,但在我们之前使用 Symfony 组件(和 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()
            );
        }
    }
    

    【讨论】:

    • 方法:->getMockBuilder从何而来?有没有办法在加载夹具时创建模拟?
    • 原始答案错过了 extends \PHPUnit_Framework_TestCase 位,它是 PHPUnit 测试的基类,它提供了 getMockBuilder() 方法。 OP 问题和这个示例主要关注如何模拟存储库(及其返回),例如,当您使用 Doctrine Fixtures 时,AFAIK 这意味着您不会模拟存储库调用,而只会在内存中拥有某种 dbms(sqlite? ) 运行测试。
    猜你喜欢
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    • 2013-09-23
    • 2017-08-16
    • 1970-01-01
    相关资源
    最近更新 更多