Example below shows us how to test Symfony constraint validators with PHPUnit.


EmailValidator


declare(strict_types=1);

namespace AppBundle\Validator\Constraint\Registration;

use AppBundle\Repository\RegistrationRepositoryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class EmailValidator extends ConstraintValidator
{
private $registrationRepository;

public function __construct(
RegistrationRepositoryInterface $registrationRepository
) {
$this->registrationRepository = $registrationRepository;
}

public function validate($value, Constraint $constraint): void
{
if (!empty($this->registrationRepository->findByEmail($value))) {
$this->context->buildViolation('The email address has already been used.')->addViolation();
}
}
}

EmailValidatorTest


declare(strict_types=1);

namespace Tests\AppBundle\Validator\Constraint\Registration;

use AppBundle\Repository\RegistrationRepositoryInterface;
use AppBundle\Validator\Constraint\Registration\EmailValidator;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
use Tests\DataFixtures\Entity\RegistrationData;

class EmailValidatorTest extends TestCase
{
/** @var RegistrationRepositoryInterface|PHPUnit_Framework_MockObject_MockObject */
private $registrationRepositoryMock;
/** @var EmailValidator */
private $emailValidator;

protected function setUp()
{
$this->registrationRepositoryMock = $this->getMockBuilder(RegistrationRepositoryInterface::class)
->disableOriginalConstructor()
->getMock();

$this->emailValidator = new EmailValidator($this->registrationRepositoryMock);
}

/**
* @test
*/
public function validate_builds_violation_if_registration_object_already_exists()
{
$value = 'email_goes_here';
$registrationEntity = RegistrationData::get();

$this->registrationRepositoryMock
->expects($this->once())
->method('findByEmail')
->willReturn([$registrationEntity]);

/** @var ExecutionContextInterface|PHPUnit_Framework_MockObject_MockObject $executionContextMock */
$executionContextMock = $this->getMockBuilder(ExecutionContextInterface::class)
->disableOriginalConstructor()
->getMock();

/** @var ConstraintViolationBuilderInterface|PHPUnit_Framework_MockObject_MockObject $executionContextMock */
$constraintViolationBuilderMock = $this->getMockBuilder(ConstraintViolationBuilderInterface::class)
->disableOriginalConstructor()
->getMock();

$executionContextMock
->expects($this->once())
->method('buildViolation')
->with('The email address has already been used.')
->willReturn($constraintViolationBuilderMock);

$constraintViolationBuilderMock
->expects($this->once())
->method('addViolation')
->willReturn(null);

/** @var Constraint|PHPUnit_Framework_MockObject_MockObject $constraintMock */
$constraintMock = $this->getMockBuilder(Constraint::class)
->disableOriginalConstructor()
->getMock();

$this->emailValidator->initialize($executionContextMock);
$this->emailValidator->validate($value, $constraintMock);
}
}

Result


$ vendor/bin/phpunit --filter EmailValidatorTest tests/AppBundle/Validator/Constraint/Registration/EmailValidatorTest.php
PHPUnit 6.3.1 by Sebastian Bergmann and contributors.

. 1 / 1 (100%)

Time: 80 ms, Memory: 6.00MB

OK (1 test, 3 assertions)