简体   繁体   English

PHPUnit 使用具有依赖关系的自定义验证器测试 Laminas 表单

[英]PHPUnit testing a Laminas form with custom validator with dependencies

I am trying to test a Laminas/Laminas-Form, that has a custom validator and this validator has a dependency that gets not injected.我正在尝试测试具有自定义验证器的 Laminas/Laminas-Form,并且该验证器具有未注入的依赖项。 If I run the application in a normal environment it is working as expected.如果我在正常环境中运行应用程序,它会按预期工作。 Only the test environment is affected.只有测试环境受到影响。

As far as I can see, if I run $myForm->isValid() at some point of the ValidationChain a new PluginManager is created if not present.据我所知,如果我在 ValidationChain 的某个点运行 $myForm->isValid() ,如果不存在,则会创建一个新的 PluginManager。 But this manager does not know the application configuration and assumes that my MyCustomValidatorWithDependencies can be invoked by using the InvokableFactory, which is obviously not the case.但是这个管理器不知道应用程序的配置,并假设我的 MyCustomValidatorWithDependencies 可以通过使用 InvokableFactory 来调用,显然不是这样。 Is there a way to inject the correct application configuration into the PluginManager or just a single factory?有没有办法将正确的应用程序配置注入到 PluginManager 或只是一个工厂? I also checked that, in a normal environment the PluginManager is present and aware of the correct factory of my MyCustomValidatorWithDependencies before and during $myForm->isValid() is executed.我还检查了,在正常环境中,PluginManager 存在并且在执行 $myForm->isValid() 之前和期间知道我的 MyCustomValidatorWithDependencies 的正确工厂。

<?php

// AppTest\Form\MyFormTest
class MyFormTest extends TestCase
{
    public function testIsValid(): void
    {
        $myForm = new MyForm();
        $myForm->setData($data);

        $makeAssertionForIsValid = $myForm->isValid();
        $makeAssertionForMessages = $myForm->getMessages();
    }
}

// App\Form\MyForm
class MyForm extends Form implements InputFilterProviderInterface {

    public function __construct() {
        parent::__construct('myFormName');
        $this->setInputFilter(new InputFilter());
    }

    public function getInputFilterSpecification(): array
    {
        return [
            'myValue' => [
                'validators' => [
                    [
                        'name' => MyCustomValidatorWithDependencies::class,
                    ],
                ],
            ],
        ];
    }
}

// App\Validator\MyCustomValidatorWithDependencies
class MyCustomValidatorWithDependencies extends AbstractValidator
{
    public function __construct(
        MyCustomDependency $myCustomDependency,
        $options = []
    ) {
        $this->myCustomDependency = $myCustomDependency;
        parent::__construct($options);
    }


    public function isValid($value) {
        // do validation...
    }
}

// App\Validator\Factory\MyCustomValidatorWithDependenciesFactory
class MyCustomValidatorWithDependenciesFactory implements FactoryInterface {
    public function __invoke(
        ContainerInterface $container,
        $requestedName,
        array $options = null
    ) {
        return new MyCustomValidatorWithDependencies(
            $container->get(MyCustomDependency::class),
            $options,
        );
    }
}


// App\config\module.config.php
return [
    'service_manager' => [
        'factories' => [
            App\Validator\MyCustomValidatorWithDependencies::class => App\Validator\Factory\MyCustomValidatorWithDependenciesFactory::class,
            App\Dependency\MyCustomDependency::class => App\Dependency\Factory\MyCustomDependencyFactory::class,
        ],
    ],
    'validators' => [
        'factories' => [
            App\Validator\MyCustomValidatorWithDependencies::class => App\Validator\Factory\MyCustomValidatorWithDependenciesFactory::class,
        ],
    ],
];

I just missed one line.我只是漏掉了一行。

$formManager = $container->get('FormElementManager');
$myForm = $formManager->get(MyForm::class);

I changed my test case to the following and it is working as I expect.我将我的测试用例更改为以下内容,它按我的预期工作。

class MyFormTest extends TestCase
{
    public function testIsValid(): void
    {
        // create a mock
        $myCustomDependency = $this->createStub(MyCustomDependency::class);

        // overwrite the factory in the application service locator to return
        // the mock instead of the real dependency.
        $container->setFactory(
            MyCustomDependency::class,
            static function () use
            (
                $myCustomDependency
            ) {
                return $myCustomDependency;
            }
        );

        // get the form
        $formManager = $container->get('FormElementManager');
        $myForm = $formManager->get(MyForm::class);
        $myForm->setData($data);

        $makeAssertionForIsValid = $myForm->isValid();
        $makeAssertionForMessages = $myForm->getMessages();
    }
}

For more information please also have a look at this discussion: https://discourse.laminas.dev/t/phpunit-testing-a-laminas-form-with-custom-validator-with-dependencies/2010有关更多信息,还请查看此讨论: https://discourse.laminas.dev/t/phpunit-testing-a-laminas-form-with-custom-validator-with-dependencies/2010
and the official docs at https://docs.laminas.dev/laminas-form/application-integration/usage-in-a-laminas-mvc-application/#create-factory-for-controller以及https://docs.laminas.dev/laminas-form/application-integration/usage-in-a-laminas-mvc-application/#create-factory-for-controller的官方文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM