Symfony 2.8.13/Doctrine ORM 2.5.5/PHPUnit 5.7.5Symfony2: Учение: PHPUnit: Установить идентификатор объекта при промывке издевались менеджера объекта в блоке тестов
Я хочу проверить метод класса, который использует администратор сущности доктрины. Этот открытый метод вызывает частный, который создает экземпляр объекта Bookmark, очищает его и возвращает этот объект. Затем в тестируемом методе мне нужно получить доступ к идентификатору объекта. Все издевается, за исключением самого объекта Bookmark. Основная проблема заключается в том, что в моей сущности не существует метода setId(). Вот код и моя основная идея решить эту проблему, но я не знаю, правильно ли это?
Испытано класс и метод
class BookmarkManager
{
//...
public function __construct(TokenStorageInterface $tokenStorage, ObjectManager $em, Session $session)
{
//...
}
public function manage($bookmarkAction, $bookmarkId, $bookmarkEntity, $bookmarkEntityId)
{
//...
$bookmark = $this->add($bookmarkEntity, $bookmarkEntityId);
//...
$bookmarkId = $bookmark->getId();
//...
}
private function add($entity, $entityId)
{
//...
$bookmark = new Bookmark();
//...
$this->em->persist($bookmark);
$this->em->flush();
return $bookmark;
}
}
Тест
class BookmarkManagerTest extends \PHPUnit_Framework_TestCase
{
public function testThatRestaurantAdditionToBookmarksIsWellManaged()
{
//...
// THIS WON'T WORK AS NO setId() METHOD EXISTS
$entityManagerMock->expects($this->once())
->method('persist')
->will($this->returnCallback(function ($bookmark) {
if ($bookmark instanceof Bookmark) {
$bookmark->setId(1);
}
}));
//...
$bookManager = new BookmarkManager($tokenStorageMock, $entityManagerMock, $sessionMock);
//...
}
}
Solutions?
1- использование Make класса отражения, как предложено here:
$entityManagerMock->expects($this->once())
->method('persist')
->will($this->returnCallback(function ($bookmark) {
if ($bookmark instanceof Bookmark) {
$class = new \ReflectionClass($bookmark);
$property = $class->getProperty('id');
$property->setAccessible(true);
$property->setValue($bookmark, 1);
//$bookmark->setId(1);
}
}));
2- Создать Boookmark объект тестирования, который простирается от реального и добавить метод SETID(). Затем создайте макет этого класса и замените и настройте тот, который был получен из метода ReturnCallback, с этим? Кажется, crappy ...
Любые мысли? Спасибо за вашу помощь.
Я знаю, что отражение должно быть злым, но я думаю, что метод отражения в вас упоминается как лучший вариант. Что-то кажется неправильным в создании классов для тестирования, таких как TestBookmark или MockEntityManager. Если вы собираетесь делать это регулярно в тестах, я нашел создание ReflectionSetterTrait, у которого есть только метод 'setProperty ($ object, $ property, $ value)', который будет полезен. – mickadoo
@mickadoo Я согласен, черта - хороший вариант. Для диспетчера сущностей я не создаю определенный класс, я просто издеваюсь над ним с помощью PHPUnit mock builder. Во всяком случае, кажется, что отражение в этом случае является решением. – Cruz