0

我正在尝试测试具有自定义验证器的 Laminas/Laminas-Form,并且该验证器具有未注入的依赖项。如果我在正常环境中运行应用程序,它会按预期工作。只有测试环境受到影响。

据我所知,如果我在 ValidationChain 的某个点运行 $myForm->isValid() ,如果不存在,则会创建一个新的 PluginManager。但是这个管理器不知道应用程序的配置,并假设我的 MyCustomValidatorWithDependencies 可以通过使用 InvokableFactory 来调用,显然不是这样。有没有办法将正确的应用程序配置注入到 PluginManager 或只是一个工厂?我还检查了,在正常环境中,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,
        ],
    ],
];
4

1 回答 1

0

我只是漏掉了一行。

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

我将我的测试用例更改为以下内容,它按我的预期工作。

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();
    }
}

有关更多信息,还请查看此讨论:https
://discourse.laminas.dev/t/phpunit-testing-a-laminas-form-with-custom-validator-with-dependencies/2010 和官方文档https://docs.laminas.dev/laminas-form/application-integration/usage-in-a-laminas-mvc-application/#create-factory-for-controller

于 2020-12-22T19:54:29.883 回答