Q:

Unit testing validator constraints

I am using Symfony2 (2.6) PHPUnit. I would like to learn how to unit test a constraint validator in symfony 2.6
The password constraint
<?php

namespace Test\MainBundle\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

class Password extends Constraint
{
    public $message = "user.password_regex";
}

The password constraint validator
<?php

namespace Test\MainBundle\Component\Validator\Constraints;

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

class PasswordValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z0-9]{6,}+$/', $value, $matches)) {
            $this->context->buildViolation($constraint->message)
                ->setParameter('%string%', $value)
                ->addViolation();
    }
}

And my test try
<?php

namespace Test\MainBundle\Tests\Component\Validator\Constraints;

use Test\MainBundle\Component\Validator\Constraints\Password;
use Test\MainBundle\Component\Validator\Constraints\PasswordValidator;

class PasswordTest extends \PHPUnit_Framework_TestCase
{
    private $constraint;

    public function setUp()
    {
        $this->constraint = new Password();
    }

    public function testFailureValidate()
    {
        $context = $this
             ->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
             ->disableOriginalConstructor()
             ->getMock();
        $context
            ->expects($this->once())
            ->method('buildViolation')
            ->with($this->constraint->message, array());

        $validator = new PasswordValidator();

        $validator->initialize($context);
        $validator->validate('test', $this->constraint);
    }

    public function testSuccessValidate()
    {
        $validator = new PasswordValidator();
        $context = $this
            ->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
            ->disableOriginalConstructor()
            ->getMock();
        $validator->initialize($context);
        $validator->validate('Testing007', $this->constraint);
    }
}

Please could you help me to solve this problem?
Thank you in advance.
If you have any good sample about unit testing in a symfony2 application, I'm very interested.

A:

We can quite easily mock "setParameter" and "addViolation" methods
something like that:
...

/**
 * @test
 * @dataProvider invalidTextProvider
 */
public function invalidItems($text)
{
    $context = $this->getMockExecutionContext();
    $context->expects($this->once())
        ->method('buildViolation')
        ->with($this->constraint->message)
        ->willReturn($this->getMockConstraintViolationBuilder())
    ;

    $this->validator->initialize($context);
    $this->validator->validate($text, $this->constraint);
}

/**
 * @return mixed
 */
private function getMockExecutionContext()
{
    $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
        ->disableOriginalConstructor()
        ->setMethods(array('buildViolation'))
        ->getMock()
    ;
    return $context;
}

private function getMockConstraintViolationBuilder()
{
    $constraintViolationBuilder = $this->getMockBuilder('Symfony\Component\Validator\Violation\ConstraintViolationBuilder')
        ->disableOriginalConstructor()
        ->getMock()
    ;
    $constraintViolationBuilder
        ->method('setParameter')
        ->willReturn($constraintViolationBuilder);
    $constraintViolationBuilder
        ->method('addViolation');
    return $constraintViolationBuilder;
}

...

