对自定义 symfony 约束进行单元测试

Posted

技术标签:

【中文标题】对自定义 symfony 约束进行单元测试【英文标题】:Unit testing a custom symfony constraint 【发布时间】:2020-12-07 21:54:50 【问题描述】:

这应该非常简单,但今天下午让我发疯了,单元测试自定义 symfony 验证器的正确方法是什么?我能找到的所有文章都和我做的完全一样

class Foo extends Constraint

    public string $message = 'The string " string " is not a valid foo.';

class FooValidator extends ConstraintValidator

    /**
     * @inheritdoc
     */
    public function validate($value, Constraint $constraint): void
    
        if ($value !== 'foo') 
            $this->context->buildViolation($constraint->message)
                ->setParameter(' string ', $value)
                ->addViolation();
        
    

class FooValidatorTest extends TestCase


    /** @test  */
    public function validate(): void
    
        $this->expectNotToPerformAssertions();

        $constraint = new Foo();
        $context    = \Mockery::mock(ExecutionContextInterface::class);
        $builder    = \Mockery::mock(ConstraintViolationBuilderInterface::class);

        $context->shouldReceive('buildViolation')
            ->with($constraint->message)
            ->andReturn($this->builder);

        $builder->shouldReceive('setParameter')
            ->with(' string ', 'foo-bar')
            ->andReturn($builder);

        $builder->shouldReceive('addViolation');

        $validator = new FooValidator();
        $validator->initialize($context);
        $validator->validate('foo-bar', $constraint);
    

这应该有效,确实有效,但是它会导致类似 9 条弃用警告


  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::setGroup()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::setConstraint()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::markGroupAsValidated()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::isGroupValidated()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::markConstraintAsValidated()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::isConstraintValidated()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::markObjectAsInitialized()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

  1x: The "Symfony\Component\Validator\Context\ExecutionContextInterface::isObjectInitialized()" method is considered internal Used by the validator engine. Should not be called by user *           code. It may change without further notice. You should not extend it from "Mockery_0_Symfony_Component_Validator_Context_ExecutionContextInterface".

由于这些方法上的 @internal 注释。因此,如果您使用 SymfonyTestsListener 并将 deprecations 设置为 0,则会导致测试失败。

有没有人知道您应该如何在不被弃用的情况下进行测试?我一直在兜圈子。我只尝试了ExecutionContextInterface的部分模拟并直接模拟了ExecutionContext并没有区别(后者也标记为@internal)。

我确信有一个非常简单的解决方案,但我一直在兜圈子,我在搜索时发现的所有内容基本上都是用 phpUnit 的 createMock 做同样的事情(以这种速度我可能只是这样做......)

【问题讨论】:

【参考方案1】:

您似乎可以将此作为示例 https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php 扩展 ConstraintValidatorTestCase... 诚然,它只是将 PHPUnit 模拟用于某些事物,而将具体类用于其他事物,但我想这是这样做的方法

【讨论】:

以上是关于对自定义 symfony 约束进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何对自定义 Wicket 组件进行单元测试

如何对自定义 AJAX 事件进行单元测试

如何对自定义 Jackson JsonSerializer 进行单元测试?

Angular2如何对自定义验证器指令进行单元测试?

如何测试自定义单元格是不是已向 tableView 注册?

Symfony4中的单元测试接口测试