带有自定义验证器的 PHPUnit ZF2 InputFilter
PHPUnit ZF2 InputFilter with Custom Validator
我有以下 InputFilter:
<?php
namespace Login\InputFilter;
use Zend\InputFilter\InputFilter;
/**
* Class Login
*
* @package Login\InputFilter
*/
class Login extends InputFilter
{
/**
* Construct
*/
public function __construct()
{
/**
* Password
*/
$this->add(
[
'name' => 'password',
'required' => true,
'filters' => [
[
'name' => 'stringtrim'
]
],
'validators' => [
[
'name' => 'stringlength',
'options' => [
'min' => '5',
'max' => '128'
],
'break_chain_on_failure' => true
],
[
'name' => 'regex',
'options' => [
'pattern' => '/^[^\\' ]+$/'
],
'break_chain_on_failure' => true
]
]
]
);
}
/**
* Init
*/
public function init()
{
/**
* Employee ID
*/
$this->add(
[
'name' => 'employeeId',
'required' => true,
'filters' => [
[
'name' => 'stringtrim'
]
],
'validators' => [
[
'name' => 'stringlength',
'options' => [
'min' => '1',
'max' => '20'
],
'break_chain_on_failure' => true
],
[
'name' => 'digits',
'break_chain_on_failure' => true
],
[
'name' => 'Login\Validator\EmployeeId',
'break_chain_on_failure' => true
]
]
]
);
}
}
附加到 employeeId
的是我创建的自定义验证器,用于检查员工 ID 是否实际存在于数据库中。它有一个 Doctrine Entity Manager 的构造函数。这在通过网络测试时工作正常,所以不用担心。
但是现在我想通过 PHPUnit
进行测试并且我创建了以下测试:
<?php
namespace LoginTest\InputFilter;
use Login\InputFilter\Login;
/**
* Class LoginTest
*
* @package LoginTest\InputFilter
*/
class LoginTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Login $inputFilter
*/
protected $inputFilter;
public function setUp()
{
$this->inputFilter = new Login();
$this->inputFilter->init();
parent::setUp();
}
public function testFormHasElements()
{
$inputs = $this->inputFilter->getInputs();
$this->assertArrayHasKey(
'employeeId',
$inputs
);
$this->assertArrayHasKey(
'password',
$inputs
);
}
}
当测试运行时产生以下错误:
1) LoginTest\InputFilter\LoginTest::testFormHasElements
Argument 1 passed to Login\Validator\EmployeeId::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /vhosts/admin-application/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php on line 180 and defined
我不确定如何才能通过这个特定错误。我假设我需要使用 Mockery,但我不确定。
验证器有一个工厂,它从服务定位器提供 Doctrine 实体管理器。
我对 PHPUnit 还是很陌生,但在来这里提问之前我一直在尝试做我的研究。
有什么想法吗?
您收到此错误是因为您直接实例化了您的输入过滤器,然后它不知道您的自定义验证器工厂。
在实际应用中,InputFilter 使用 Zend\Validator\ValidatorPluginManager
从服务管理器获取验证器。
我看到有两种方法可以解决这个问题:
1.) 您可以从应用程序配置中设置真正的服务管理器,如 documentation 中所述,然后从服务管理器中拉取输入过滤器:
$inputFilter = Bootstrap::getServiceManager()->get(\Login\InputFilter\Login::class); // change the service name if you have another
如果您想编写某种集成测试,这个解决方案很好。
2.) 您可以模拟您的自定义验证器并在设置方法中注入 ValidatorPluginManager
:
protected function setUp()
{
$validator = $this->getMockBuilder(\Login\Validator\EmployeeId::class)->getMock();
$inputFilter = new Login();
$inputFilter->getFactory()
->getDefaultValidatorChain()
->getPluginManager()
->setService(\Login\Validator\EmployeeId::class, $validator);
$inputFilter->init();
$this->inputFilter = $inputFilter;
parent::setUp();
}
如果您想为登录输入过滤器编写单元测试,这个解决方案很好。
我有以下 InputFilter:
<?php
namespace Login\InputFilter;
use Zend\InputFilter\InputFilter;
/**
* Class Login
*
* @package Login\InputFilter
*/
class Login extends InputFilter
{
/**
* Construct
*/
public function __construct()
{
/**
* Password
*/
$this->add(
[
'name' => 'password',
'required' => true,
'filters' => [
[
'name' => 'stringtrim'
]
],
'validators' => [
[
'name' => 'stringlength',
'options' => [
'min' => '5',
'max' => '128'
],
'break_chain_on_failure' => true
],
[
'name' => 'regex',
'options' => [
'pattern' => '/^[^\\' ]+$/'
],
'break_chain_on_failure' => true
]
]
]
);
}
/**
* Init
*/
public function init()
{
/**
* Employee ID
*/
$this->add(
[
'name' => 'employeeId',
'required' => true,
'filters' => [
[
'name' => 'stringtrim'
]
],
'validators' => [
[
'name' => 'stringlength',
'options' => [
'min' => '1',
'max' => '20'
],
'break_chain_on_failure' => true
],
[
'name' => 'digits',
'break_chain_on_failure' => true
],
[
'name' => 'Login\Validator\EmployeeId',
'break_chain_on_failure' => true
]
]
]
);
}
}
附加到 employeeId
的是我创建的自定义验证器,用于检查员工 ID 是否实际存在于数据库中。它有一个 Doctrine Entity Manager 的构造函数。这在通过网络测试时工作正常,所以不用担心。
但是现在我想通过 PHPUnit
进行测试并且我创建了以下测试:
<?php
namespace LoginTest\InputFilter;
use Login\InputFilter\Login;
/**
* Class LoginTest
*
* @package LoginTest\InputFilter
*/
class LoginTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Login $inputFilter
*/
protected $inputFilter;
public function setUp()
{
$this->inputFilter = new Login();
$this->inputFilter->init();
parent::setUp();
}
public function testFormHasElements()
{
$inputs = $this->inputFilter->getInputs();
$this->assertArrayHasKey(
'employeeId',
$inputs
);
$this->assertArrayHasKey(
'password',
$inputs
);
}
}
当测试运行时产生以下错误:
1) LoginTest\InputFilter\LoginTest::testFormHasElements
Argument 1 passed to Login\Validator\EmployeeId::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /vhosts/admin-application/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php on line 180 and defined
我不确定如何才能通过这个特定错误。我假设我需要使用 Mockery,但我不确定。
验证器有一个工厂,它从服务定位器提供 Doctrine 实体管理器。
我对 PHPUnit 还是很陌生,但在来这里提问之前我一直在尝试做我的研究。
有什么想法吗?
您收到此错误是因为您直接实例化了您的输入过滤器,然后它不知道您的自定义验证器工厂。
在实际应用中,InputFilter 使用 Zend\Validator\ValidatorPluginManager
从服务管理器获取验证器。
我看到有两种方法可以解决这个问题:
1.) 您可以从应用程序配置中设置真正的服务管理器,如 documentation 中所述,然后从服务管理器中拉取输入过滤器:
$inputFilter = Bootstrap::getServiceManager()->get(\Login\InputFilter\Login::class); // change the service name if you have another
如果您想编写某种集成测试,这个解决方案很好。
2.) 您可以模拟您的自定义验证器并在设置方法中注入 ValidatorPluginManager
:
protected function setUp()
{
$validator = $this->getMockBuilder(\Login\Validator\EmployeeId::class)->getMock();
$inputFilter = new Login();
$inputFilter->getFactory()
->getDefaultValidatorChain()
->getPluginManager()
->setService(\Login\Validator\EmployeeId::class, $validator);
$inputFilter->init();
$this->inputFilter = $inputFilter;
parent::setUp();
}
如果您想为登录输入过滤器编写单元测试,这个解决方案很好。