Есть ли способ создать макет диспетчера сущностей Doctrine 2 и предоставить ему макет объекта в тесте PHPUnit Symfony 2?

#php #symfony #doctrine-orm #phpunit

#php #symfony #doctrine-orm #phpunit

Вопрос:

Мне было поручено написать модульные тесты для устаревшего кода. Мой текущий тест проводится на объекте, который принимает диспетчер сущностей Doctrine 2 в качестве параметра конструктора. Мне нужно иметь возможность передавать ему тестовые данные, чтобы я мог надежно протестировать его методы.

Итак, в идеале я хотел бы иметь возможность создать макет менеджера сущностей, затем создать макет объекта и прикрепить его к макету entity manager, а затем использовать его в своих тестах. Возможно ли это? Если да, то как?

В этом проекте используется Symfony 2.4 , поэтому я уверен, что это добавляет одну или две проблемы в настройке.

Ответ №1:

Не уверен, будет ли это применимо или нет к вашим конкретным потребностям в настройке Symfony (full stack?), Но в предыдущих проектах, где мы использовали компоненты Symfony (и Doctrine), но не полный стек, это была более или менее следующая настройка:

 <?php

namespace TestsSomeNameSpace;

use DoctrineORMEntityRepository;
use SomeNameSpaceRepositoriesSomeRepository;
use SomeNameSpaceSubjectUnderTesting;

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 DoctrineORMEntityRepository
         */
        $repository = $this
            ->getMockBuilder('DoctrineORMEntityRepository')
            ->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 DoctrineORMEntityManager
         */
        $entityManager = $this
            ->getMockBuilder('DoctrineORMEntityManager')
            ->setMethods(array('getRepository'))
            ->disableOriginalConstructor()
            ->getMock();

        $entityManager
            ->expects($this->once())
            ->method('getRepository')
            ->with('SomeNameSpaceRepositoriesSomeRepository')
            ->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('SomeNameSpaceRepositoriesSomeRepository')
         *     ->findOneByEmail($someEmail);
         *
         * @var SubjectUnderTesting
         */
        $sut = new SubjectUnderTesting($entityManager);

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

        $this->assertEquals(
            $expected,
            $sut->callSomeMethodToTestThatDependsOnSomeQueryByEmail()
        );
    }
}
 

Комментарии:

1. Откуда взялся метод: ->getMockBuilder? Есть ли способ создавать макеты при загрузке приспособлений?

2. В исходном ответе пропущен extends PHPUnit_Framework_TestCase бит, который является базовым классом для тестов PHPUnit и который предоставляет getMockBuilder() метод. Вопрос OP и этот пример сосредоточены в основном на том, как имитировать репозитории (и их возвраты), например, когда вы используете Doctrine Fixtures, это означает, что вы не будете издеваться над вызовами репозитория и просто иметь какую-то СУБД в памяти (sqlite?) для запуска тестов.