7

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.

4
  • Where specifically in your test do things go wrong? Commented Mar 7, 2015 at 21:30
  • Actually I get PHP Fatal error: Call to undefined method Mock_ExecutionContext_a2d8943d::buildViolation() on the testFailureValidate() Commented Mar 7, 2015 at 21:34
  • 2
    Problem can be caused by mocking Symfony's context (setParameter, addViolation is not mocked). I typically don't test this Symfony boilerplate (I don't care about constraint, context and violations). I simply extract method from if and test only the method that returns boolean. In your case I would test public method isPasswordInvalid. Commented Mar 8, 2015 at 8:30
  • Thanks a lot finally I agree with your solution. Do you have any good sample about unit testing in a symfony2 application? Commented Mar 10, 2015 at 9:30

1 Answer 1

2

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;
}

...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.