Example below tests class level custom assert validation constraint.


Validation constraint class


namespace Application\BackendBundle\Validator\Constraint;

use Symfony\Component\Validator\Constraint;

/**
* @Annotation
*/
class UserCreate extends Constraint
{
const INVALID_USERNAME = 'Username must form of only alphabetic and numeric characters.';
const MIN_PASSWORD = 'Password cannot be less than 6 characters.';
const USERNAME_PASSWORD_MATCH = 'Username and Password cannot be same.';

public function getTargets()
{
return self::CLASS_CONSTRAINT;
}

public function validatedBy()
{
return get_class($this).'Validator';
}
}

namespace Application\BackendBundle\Validator\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UserCreateValidator extends ConstraintValidator
{
public function validate($userCreate, Constraint $constraint)
{
if (! ctype_alnum($userCreate->username)) {
$this->context
->buildViolation($constraint::INVALID_USERNAME)
->atPath('username')
->addViolation();
} else if (mb_strlen(trim($userCreate->password)) < 6) {
$this->context
->buildViolation($constraint::MIN_PASSWORD)
->atPath('password')
->addViolation();
} else if ($userCreate->username == $userCreate->password) {
$this->context
->buildViolation($constraint::USERNAME_PASSWORD_MATCH)
->atPath('username_password_match')
->addViolation();
}
}
}

PhpSpec


namespace spec\Application\BackendBundle\Validator\Constraint;

use Application\BackendBundle\Model\User\Create;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
use Application\BackendBundle\Validator\Constraint\UserCreate as Constraint;

class UserCreateValidatorSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Application\BackendBundle\Validator\Constraint\UserCreateValidator');
}

function it_should_not_validate_illegal_characters(
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
Constraint $constraint,
Create $create
) {
$create->username = 'ab@£$123';

$this->initialize($context);

$builder->addViolation()->shouldBeCalled();
$builder->atPath('username')->willReturn($builder);

$context->buildViolation(
'Username must form of only alphabetic and numeric characters.'
)->willReturn($builder);

$this->validate($create, $constraint);
}

function it_should_not_validate_short_password(
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
Constraint $constraint,
Create $create
) {
$create->username = 'inanzzz';
$create->password = '123';

$this->initialize($context);

$builder->addViolation()->shouldBeCalled();
$builder->atPath('password')->willReturn($builder);

$context->buildViolation(
'Password cannot be less than 6 characters.'
)->willReturn($builder);

$this->validate($create, $constraint);
}

function it_should_not_validate_same_username_and_password(
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
Constraint $constraint,
Create $create
) {
$create->username = 'inanzzz';
$create->password = 'inanzzz';

$this->initialize($context);

$builder->addViolation()->shouldBeCalled();
$builder->atPath('username_password_match')->willReturn($builder);

$context->buildViolation(
'Username and Password cannot be same.'
)->willReturn($builder);

$this->validate($create, $constraint);
}

function it_should_validate_legal_values(
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
Constraint $constraint,
Create $create
) {
$create->username = 'inanzzz';
$create->password = '123456';

$this->initialize($context);

$builder->addViolation()->shouldNotBeCalled();

$this->validate($create, $constraint);
}
}