单元测试自定义验证器

发布于 2025-02-09 01:57:13 字数 3619 浏览 2 评论 0 原文

我的验证器看起来像:

<?php

declare(strict_types=1);

namespace App\Infrastructure\Domain\Model\Company\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Contracts\Translation\TranslatorInterface;

final class ContainsUnsupportedSymbolsValidator extends ConstraintValidator
{
    public function __construct(
        private TranslatorInterface $translator
    )
    {
    }

    public function validate($value, Constraint $constraint): void
    {
        if (!$constraint instanceof ContainsUnsupportedSymbols) {
            throw new UnexpectedTypeException($constraint, ContainsUnsupportedSymbols::class);
        }

        // custom constraints should ignore null and empty values to allow
        // other constraints (NotBlank, NotNull, etc.) to take care of that
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_string($value)) {
            // throw this exception if your validator cannot handle the passed type so that it can be marked as invalid
            throw new UnexpectedValueException($value, 'string');
        }

        if (!preg_match('/^\+?[0-9]{3}-?[0-9]{6,12}$/', $value, $matches)) {
            // the argument must be a string or an object implementing __toString()
            $this->context->buildViolation(
                $this->translator->trans($constraint->message, ['{phone}' => $value])
            )->addViolation();
        }
    }
}

我为有效案例编写的测试是:

<?php

declare(strict_types=1);

namespace App\Tests\Unit\Infrastructure\Domain\Model\Company\Validator;

use App\Infrastructure\Domain\Model\Company\Validator\ContainsUnsupportedSymbols;
use App\Infrastructure\Domain\Model\Company\Validator\ContainsUnsupportedSymbolsValidator;
use App\Tests\Unit\UnitTestCase;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final class ContainsUnsupportedSymbolsValidatorTest extends UnitTestCase
{
    public function testValidatorWithValidPhone():void
    {
        $phone = "+359883202020";

        $translationMock = $this->createMock(TranslatorInterface::class);

        $constraint = new ContainsUnsupportedSymbols();

        $constraintValidator = new ContainsUnsupportedSymbolsValidator($translationMock);

        $this->assertEmpty($constraintValidator->validate($phone, $constraint));
    }
}

使用 assementy 测试是否正确。 ? 以及如何使用错误的数据测试?试图模拟上下文 buildviolation addviolation 方法,但有错误:

错误:在null上致电成员函数buildviolation()

这是我尝试使用不正确的电话

public function testValidatorWithInvalidPhone():void
    {
        $phone = "+359()883202020";

        $translationMock = $this->createMock(TranslatorInterface::class);

        $contextMock = $this->createMock(ExecutionContextInterface::class);
        $contextMock->expects($this->once())
            ->method('buildViolation')
            ->with('message');
        $contextMock->expects($this->once())
            ->method('addViolation');

        $constraint = new ContainsUnsupportedSymbols();

        $constraintValidator = new ContainsUnsupportedSymbolsValidator($translationMock);

        $this->assertEmpty($constraintValidator->validate($phone, $constraint));
    }

My validator looks like:

<?php

declare(strict_types=1);

namespace App\Infrastructure\Domain\Model\Company\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Contracts\Translation\TranslatorInterface;

final class ContainsUnsupportedSymbolsValidator extends ConstraintValidator
{
    public function __construct(
        private TranslatorInterface $translator
    )
    {
    }

    public function validate($value, Constraint $constraint): void
    {
        if (!$constraint instanceof ContainsUnsupportedSymbols) {
            throw new UnexpectedTypeException($constraint, ContainsUnsupportedSymbols::class);
        }

        // custom constraints should ignore null and empty values to allow
        // other constraints (NotBlank, NotNull, etc.) to take care of that
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_string($value)) {
            // throw this exception if your validator cannot handle the passed type so that it can be marked as invalid
            throw new UnexpectedValueException($value, 'string');
        }

        if (!preg_match('/^\+?[0-9]{3}-?[0-9]{6,12}$/', $value, $matches)) {
            // the argument must be a string or an object implementing __toString()
            $this->context->buildViolation(
                $this->translator->trans($constraint->message, ['{phone}' => $value])
            )->addViolation();
        }
    }
}

The test I wrote for valid case is:

<?php

declare(strict_types=1);

namespace App\Tests\Unit\Infrastructure\Domain\Model\Company\Validator;

use App\Infrastructure\Domain\Model\Company\Validator\ContainsUnsupportedSymbols;
use App\Infrastructure\Domain\Model\Company\Validator\ContainsUnsupportedSymbolsValidator;
use App\Tests\Unit\UnitTestCase;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final class ContainsUnsupportedSymbolsValidatorTest extends UnitTestCase
{
    public function testValidatorWithValidPhone():void
    {
        $phone = "+359883202020";

        $translationMock = $this->createMock(TranslatorInterface::class);

        $constraint = new ContainsUnsupportedSymbols();

        $constraintValidator = new ContainsUnsupportedSymbolsValidator($translationMock);

        $this->assertEmpty($constraintValidator->validate($phone, $constraint));
    }
}

Is it correct to test with assertEmpty when the validate method return type is void?
And how to test with incorrect data? Tried to mock the context and both buildViolation and addViolation methods but got error:

Error: Call to a member function buildViolation() on null

This is what I tried with incorrect phone

public function testValidatorWithInvalidPhone():void
    {
        $phone = "+359()883202020";

        $translationMock = $this->createMock(TranslatorInterface::class);

        $contextMock = $this->createMock(ExecutionContextInterface::class);
        $contextMock->expects($this->once())
            ->method('buildViolation')
            ->with('message');
        $contextMock->expects($this->once())
            ->method('addViolation');

        $constraint = new ContainsUnsupportedSymbols();

        $constraintValidator = new ContainsUnsupportedSymbolsValidator($translationMock);

        $this->assertEmpty($constraintValidator->validate($phone, $constraint));
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故事↓在人 2025-02-16 01:57:16

您的上下文是无效的。您必须初始化由自定义验证器扩展的 CondraintValidator
这个问题在这里找到了一个答案:单位测试自定义符号约束

简短这是一个示例

在示例中,测试类扩展了 consect> CODE> CONDER> CONDER> CONDERTVALIDATETTESTESTCASE 上下文(在这里查看:

Your context is null. You have to initialize the ConstraintValidator extended by your custom validator.
The question has found an answer here: Unit testing a custom symfony constraint

In short here is an example https://github.com/symfony/symfony/blob/6.2/src/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php

In the example the test class extends ConstraintValidatorTestCase that defines a context (look here: https://github.com/symfony/validator/blob/6.1/Test/ConstraintValidatorTestCase.php)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文