Статья о модульном тестировании сущности в symfony 4 относительно валидации.
Можно тестировать корректную обработку валидных и на невалидных данных в функциональных тестах. Но это занимает много времени, так как загружается все приложение со всеми зависимостями, база данных и т.д. и т.п.
Как ускорить тестирование?
В документации symfony по этому поводу написано:
Don’t test the validation: it is applied by a listener that is not active in the test case and it relies on validation configuration. Instead, unit test your custom constraints directly.
Поэтому тестирование можно упростить: загрузить валидатор для сущности, скормить ему объект с валидными (или невалидными) данными и проверить результат. Никакой авторизации, фикстур, заполнения форм и других телодвижений.
Допустим, у нас есть сущность MyEntity с полями name, description и ограничениями на name: не null, minLenght, maxLenght. Проверить, установлены ли нужные ограничения (с использованием phpunit) можно так:
<?php
namespace App\Tests\Controller\Admin;
use App\Entity\MyEntity;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\Validation;
class MyEntityValidationTest extends TestCase
{
/**
* @dataProvider getMyEntityInvalidData
*/
public function testMyEntityIsInvalid($name, $description)
{
// enableAnnotationMapping для ограничений в аннотациях
$validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();
// если ограничения например в yaml, то надо так:
/*
$validator = Validation::createValidatorBuilder()->addYamlMapping('/your/path/to/validitor/validation.yaml')->getValidator();
*/
$quest = new MyEntity();
$quest->setName($name);
$quest->setDescription($description);
/** @var ConstraintViolation[] $violations */
$violations = $validator->validate($quest);
$this->assertTrue(count($violations) = 1);
}
public function getMyEntityInvalidData()
{
// null name
yield ['name' => null, 'description' => 'valid description'];
// invalid name length
yield ['name' => '1', 'description' => 'valid description'];
//invalid name length
yield [
'name' => 'qwjdhfnvjcnfhvn nvhf chfn ndnwb nvbchf r nfnefhvn nvjdhf2',
'description' => 'valid description',
];
}
Может возникнуть проблема со сложными ограничениями, например на уникальность. Если у вас доктрина, то во время выполнения теста возникнет ошибка
doctrine.orm.validator.unique’ not found
так как никакая orm в этот тесте не существует.
Это проблему можно решить так: разделить простые и сложные валидации по разным источникам(одни в аннотациях, другие в yaml), и в модульных тестах загружать и проверять только простые. Костыль, но для достижения цели (ускорения) работает.
А сложные ограничения, с базой данных, проверять уже в функциональных. Выигрыш во времени будет. Наверное, можно сделать заглушку для валидатора, но это уже другая история.