#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?) для запуска тестов.