Skip to content

Commit

Permalink
bug #42458 [Validator][Tests] Fix AssertingContextualValidator not th…
Browse files Browse the repository at this point in the history
…rowing on remaining expectations (fancyweb)

This PR was merged into the 4.4 branch.

Discussion
----------

[Validator][Tests] Fix AssertingContextualValidator not throwing on remaining expectations

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

While working on something I noticed two missing things in the `AssertingContextualValidator`.

1. We don't check if there are remaining expected calls when the `AssertingContextualValidator` is destroyed. Therefore the tests using it always pass, whether the validator actually calls `validate` or not. (for example: comment the `->validate()` line in `AllValidator` and tests still pass)
~2. When the expected value / value is an object, we should use `assertEquals` because it cannot logically be the same instance.~

Ping `@xabbuh`

Commits
-------

aac1013 [Validator][Tests] Fix AssertingContextualValidator not throwing on remaining expectations
  • Loading branch information
nicolas-grekas committed Feb 23, 2022
2 parents 46408f0 + aac1013 commit 75bf7fa
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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(),
]);
}
}

0 comments on commit 75bf7fa

Please sign in to comment.