From aac10136097b92e6bd03043525b235f31ea480f1 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Mon, 9 Aug 2021 18:38:29 +0200 Subject: [PATCH] [Validator][Tests] Fix AssertingContextualValidator not throwing on remaining expectations --- .../Test/ConstraintValidatorTestCase.php | 17 ++++- .../Test/ConstraintValidatorTestCaseTest.php | 71 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Test/ConstraintValidatorTestCaseTest.php diff --git a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php index 087bbf140fb2a..1d75a6bb3b026 100644 --- a/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Test/ConstraintValidatorTestCase.php @@ -391,6 +391,17 @@ class AssertingContextualValidator implements ContextualValidatorInterface private $validateCalls = -1; private $expectedValidate = []; + public function __destruct() + { + if ($this->expectedAtPath) { + throw new ExpectationFailedException('Some expected validation calls for paths were not done.'); + } + + if ($this->expectedValidate) { + throw new ExpectationFailedException('Some expected validation calls for values were not done.'); + } + } + public function atPath($path) { } @@ -403,7 +414,10 @@ public function doAtPath($path) throw new ExpectationFailedException(sprintf('Validation for property path "%s" was not expected.', $path)); } - Assert::assertSame($this->expectedAtPath[$this->atPathCalls], $path); + $expectedPath = $this->expectedAtPath[$this->atPathCalls]; + unset($this->expectedAtPath[$this->atPathCalls]); + + Assert::assertSame($expectedPath, $path); return $this; } @@ -417,6 +431,7 @@ public function doValidate($value, $constraints = null, $groups = null) Assert::assertFalse($this->expectNoValidate, 'No validation calls have been expected.'); [$expectedValue, $expectedGroup, $expectedConstraints] = $this->expectedValidate[++$this->validateCalls]; + unset($this->expectedValidate[$this->validateCalls]); Assert::assertSame($expectedValue, $value); $expectedConstraints($constraints); diff --git a/src/Symfony/Component/Validator/Tests/Test/ConstraintValidatorTestCaseTest.php b/src/Symfony/Component/Validator/Tests/Test/ConstraintValidatorTestCaseTest.php new file mode 100644 index 0000000000000..70b6065e1a134 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Test/ConstraintValidatorTestCaseTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Test; + +use PHPUnit\Framework\ExpectationFailedException; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\DateTime; +use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\ConstraintValidatorInterface; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; + +class ConstraintValidatorTestCaseTest extends ConstraintValidatorTestCase +{ + protected function createValidator(): ConstraintValidatorInterface + { + return new TestCustomValidator(); + } + + public function testAssertingContextualValidatorRemainingExpectationsThrow() + { + $this->expectValidateValueAt(0, 'k1', 'ccc', [ + new NotNull(), + ]); + $this->expectValidateValueAt(1, 'k2', 'ccc', [ + new DateTime(), + ]); + + $this->validator->validate('ccc', $this->constraint); + + $contextualValidator = $this->context->getValidator()->inContext($this->context); + // Simulate __destruct to assert it throws + try { + $contextualValidator->__destruct(); + $this->fail(); + } catch (ExpectationFailedException $e) { + } + + // Actually fulfill expectations so real __destruct doesn't throw + $contextualValidator + ->atPath('k2') + ->validate('ccc', [ + new DateTime(), + ]); + } +} + +class TestCustomValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + $validator = $this->context + ->getValidator() + ->inContext($this->context); + + $validator + ->atPath('k1') + ->validate($value, [ + new NotNull(), + ]); + } +}