PHPUnit 使用具有依赖关系的自定义验证器测试 Laminas 表单
PHPUnit testing a Laminas form with custom validator with dependencies
我正在尝试测试一个 Laminas/Laminas-Form,它有一个自定义验证器,并且这个验证器有一个没有注入的依赖项。
如果我 运行 正常环境中的应用程序它按预期工作。只有测试环境受到影响。
据我所知,如果我 运行 $myForm->isValid() 在 ValidationChain 的某个点创建一个新的 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,
],
],
];
我只漏了一行。
$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
的官方文档
我正在尝试测试一个 Laminas/Laminas-Form,它有一个自定义验证器,并且这个验证器有一个没有注入的依赖项。 如果我 运行 正常环境中的应用程序它按预期工作。只有测试环境受到影响。
据我所知,如果我 运行 $myForm->isValid() 在 ValidationChain 的某个点创建一个新的 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,
],
],
];
我只漏了一行。
$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