4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Validator\Tests\Constraints;
14 use PHPUnit\Framework\Assert;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Validator\Constraint;
17 use Symfony\Component\Validator\Constraints\NotNull;
18 use Symfony\Component\Validator\ConstraintValidatorInterface;
19 use Symfony\Component\Validator\ConstraintViolation;
20 use Symfony\Component\Validator\Context\ExecutionContext;
21 use Symfony\Component\Validator\Context\ExecutionContextInterface;
22 use Symfony\Component\Validator\Context\LegacyExecutionContext;
23 use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface;
24 use Symfony\Component\Validator\Mapping\ClassMetadata;
25 use Symfony\Component\Validator\Mapping\PropertyMetadata;
26 use Symfony\Component\Validator\Validation;
29 * @author Bernhard Schussek <bschussek@gmail.com>
31 abstract class AbstractConstraintValidatorTest extends TestCase
34 * @var ExecutionContextInterface
39 * @var ConstraintValidatorInterface
48 protected $propertyPath;
49 protected $constraint;
50 protected $defaultTimezone;
52 protected function setUp()
54 $this->group = 'MyGroup';
55 $this->metadata = null;
57 $this->value = 'InvalidValue';
59 $this->propertyPath = 'property.path';
61 // Initialize the context with some constraint so that we can
62 // successfully build a violation.
63 $this->constraint = new NotNull();
65 $this->context = $this->createContext();
66 $this->validator = $this->createValidator();
67 $this->validator->initialize($this->context);
69 \Locale::setDefault('en');
71 $this->setDefaultTimezone('UTC');
74 protected function tearDown()
76 $this->restoreDefaultTimezone();
79 protected function setDefaultTimezone($defaultTimezone)
81 // Make sure this method can not be called twice before calling
82 // also restoreDefaultTimezone()
83 if (null === $this->defaultTimezone) {
84 $this->defaultTimezone = date_default_timezone_get();
85 date_default_timezone_set($defaultTimezone);
89 protected function restoreDefaultTimezone()
91 if (null !== $this->defaultTimezone) {
92 date_default_timezone_set($this->defaultTimezone);
93 $this->defaultTimezone = null;
97 protected function createContext()
99 $translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
100 $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock();
101 $contextualValidator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ContextualValidatorInterface')->getMock();
103 switch ($this->getApiVersion()) {
104 case Validation::API_VERSION_2_5:
105 $context = new ExecutionContext(
111 case Validation::API_VERSION_2_4:
112 case Validation::API_VERSION_2_5_BC:
113 $context = new LegacyExecutionContext(
116 $this->getMockBuilder('Symfony\Component\Validator\MetadataFactoryInterface')->getMock(),
121 throw new \RuntimeException('Invalid API version');
124 $context->setGroup($this->group);
125 $context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
126 $context->setConstraint($this->constraint);
128 $validator->expects($this->any())
129 ->method('inContext')
131 ->will($this->returnValue($contextualValidator));
137 * @param mixed $message
138 * @param array $parameters
139 * @param string $propertyPath
140 * @param string $invalidValue
141 * @param null $plural
144 * @return ConstraintViolation
146 * @deprecated to be removed in Symfony 3.0. Use {@link buildViolation()} instead.
148 protected function createViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
150 return new ConstraintViolation(
163 protected function setGroup($group)
165 $this->group = $group;
166 $this->context->setGroup($group);
169 protected function setObject($object)
171 $this->object = $object;
172 $this->metadata = is_object($object)
173 ? new ClassMetadata(get_class($object))
176 $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
179 protected function setProperty($object, $property)
181 $this->object = $object;
182 $this->metadata = is_object($object)
183 ? new PropertyMetadata(get_class($object), $property)
186 $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
189 protected function setValue($value)
191 $this->value = $value;
192 $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
195 protected function setRoot($root)
198 $this->context = $this->createContext();
199 $this->validator->initialize($this->context);
202 protected function setPropertyPath($propertyPath)
204 $this->propertyPath = $propertyPath;
205 $this->context->setNode($this->value, $this->object, $this->metadata, $this->propertyPath);
208 protected function expectNoValidate()
210 $validator = $this->context->getValidator()->inContext($this->context);
211 $validator->expects($this->never())
213 $validator->expects($this->never())
214 ->method('validate');
217 protected function expectValidateAt($i, $propertyPath, $value, $group)
219 $validator = $this->context->getValidator()->inContext($this->context);
220 $validator->expects($this->at(2 * $i))
222 ->with($propertyPath)
223 ->will($this->returnValue($validator));
224 $validator->expects($this->at(2 * $i + 1))
226 ->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group);
229 protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null)
231 $contextualValidator = $this->context->getValidator()->inContext($this->context);
232 $contextualValidator->expects($this->at(2 * $i))
234 ->with($propertyPath)
235 ->will($this->returnValue($contextualValidator));
236 $contextualValidator->expects($this->at(2 * $i + 1))
238 ->with($value, $constraints, $group);
241 protected function assertNoViolation()
243 $this->assertSame(0, $violationsCount = count($this->context->getViolations()), sprintf('0 violation expected. Got %u.', $violationsCount));
247 * @param mixed $message
248 * @param array $parameters
249 * @param string $propertyPath
250 * @param string $invalidValue
251 * @param null $plural
254 * @deprecated To be removed in Symfony 3.0. Use
255 * {@link buildViolation()} instead.
257 protected function assertViolation($message, array $parameters = array(), $propertyPath = 'property.path', $invalidValue = 'InvalidValue', $plural = null, $code = null)
259 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
261 $this->buildViolation($message)
262 ->setParameters($parameters)
263 ->atPath($propertyPath)
264 ->setInvalidValue($invalidValue)
271 * @param array $expected
273 * @deprecated To be removed in Symfony 3.0. Use
274 * {@link buildViolation()} instead.
276 protected function assertViolations(array $expected)
278 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0. Use the buildViolation() method instead.', E_USER_DEPRECATED);
280 $violations = $this->context->getViolations();
282 $this->assertCount(count($expected), $violations);
286 foreach ($expected as $violation) {
287 $this->assertEquals($violation, $violations[$i++]);
294 * @return ConstraintViolationAssertion
296 protected function buildViolation($message)
298 return new ConstraintViolationAssertion($this->context, $message, $this->constraint);
301 protected function getApiVersion()
303 return Validation::API_VERSION_2_5;
306 abstract protected function createValidator();
312 class ConstraintViolationAssertion
315 * @var LegacyExecutionContextInterface
320 * @var ConstraintViolationAssertion[]
325 private $parameters = array();
326 private $invalidValue = 'InvalidValue';
327 private $propertyPath = 'property.path';
328 private $translationDomain;
334 public function __construct(LegacyExecutionContextInterface $context, $message, Constraint $constraint = null, array $assertions = array())
336 $this->context = $context;
337 $this->message = $message;
338 $this->constraint = $constraint;
339 $this->assertions = $assertions;
342 public function atPath($path)
344 $this->propertyPath = $path;
349 public function setParameter($key, $value)
351 $this->parameters[$key] = $value;
356 public function setParameters(array $parameters)
358 $this->parameters = $parameters;
363 public function setTranslationDomain($translationDomain)
365 $this->translationDomain = $translationDomain;
370 public function setInvalidValue($invalidValue)
372 $this->invalidValue = $invalidValue;
377 public function setPlural($number)
379 $this->plural = $number;
384 public function setCode($code)
391 public function setCause($cause)
393 $this->cause = $cause;
398 public function buildNextViolation($message)
400 $assertions = $this->assertions;
401 $assertions[] = $this;
403 return new self($this->context, $message, $this->constraint, $assertions);
406 public function assertRaised()
409 foreach ($this->assertions as $assertion) {
410 $expected[] = $assertion->getViolation();
412 $expected[] = $this->getViolation();
414 $violations = iterator_to_array($this->context->getViolations());
416 Assert::assertSame($expectedCount = count($expected), $violationsCount = count($violations), sprintf('%u violation(s) expected. Got %u.', $expectedCount, $violationsCount));
420 foreach ($expected as $violation) {
421 Assert::assertEquals($violation, current($violations));
426 private function getViolation()
428 return new ConstraintViolation(
432 $this->context->getRoot(),