Take the 2-minute tour ×

How can i unit test ContainsItalianVatinValidator custom validator, but w*ithout accessing the container* and the validator service (and thus, create a stub object)?

class ContainsItalianVatinValidator extends ConstraintValidator
     * @param mixed $value
     * @param \Symfony\Component\Validator\Constraint $constraint
    public function validate($value, Constraint $constraint)
        if (!preg_match('/^[0-9]{11}$/', $value, $matches)) {
            $this->context->addViolation($constraint->message, array(
                '%string%' => $value

        // Compute and check control code
        // ...

In my test case i know i should access the ConstraintViolationList, but i don't know how to do it from the validator itself:

class ContainsItalianVatinValidatorTest extends \PHPUnit_Framework_TestCase
    public function testEmptyItalianVatin()
        $emptyVatin = '';
        $validator  = new ContainsItalianVatinValidator();
        $constraint = new ContainsItalianVatinConstraint();

        // Do the validation
        $validator->validate($emptyVatin, $constraint);

        // How can a get a violation list and call ->count()?
        $violations = /* ... */;

        // Assert
        $this->assertGreaterThan(0, $violations->count());
share|improve this question
add comment

1 Answer

up vote 9 down vote accepted

When you take a look at the parent class of the validator Symfony\Component\Validator\ConstraintValidator you see that there is a method called initialize which takes an instance of Symfony\Component\Validator\ExecutionContext as argument.

After you created the validator you can call the initialize method and pass a mock context to the validator. You don't have to test if the addViolation method works correctly, you only have to test if it is called and if it is called with the correct parameters. You can do that with the mock functionality of PHPUnit.

$validator  = new ContainsItalianVatinValidator();
$context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')-> disableOriginalConstructor()->getMock();

    ->with($this->equalTo('[message]'), $this->equalTo(array('%string%', '')));



In this code you have to replace [message] with the message stored in $constraint->message.

Actually, this question is more related to PHPUnit than to Symfony. You may find the Test Doubles chapter of the PHPUnit documentation interesting.

share|improve this answer
Amazing good explanation. The only thing i can't get is why, in your opinion, counting violations is wrong and why i should prefer to rely on the constraint message itself. Anyway, +1. –  gremo Sep 12 '12 at 22:52
Why should you count the violations. At least in the code in your question there is only one call to addViolation. If that method is called one time exactly one violation will be added to the context (the unit tests of Symfony2 test that). –  Florian Eckerstorfer Sep 12 '12 at 23:01
If there should be more calls to addViolation in the code you could add multiple $context->expects statements where each covers one different call to addViolation. Sadly PHPUnit does only offer two methods to count the number of calls of a method once and any. However, Mockery is a mock library that is compatible with PHPUnit and can count the number of method calls on a mock object. –  Florian Eckerstorfer Sep 12 '12 at 23:04
Thanks, i'll go for checking calls to addViolation. –  gremo Sep 12 '12 at 23:06
add comment

Your Answer


