【问题标题】:PHPUnit ZF2 InputFilter with Custom Validator带有自定义验证器的 PHPUnit ZF2 InputFilter
【发布时间】:2015-03-28 02:54:40
【问题描述】:

我有以下输入过滤器:

<?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 Entity Manager。

我对 PHPUnit 还是很陌生,但在问这里之前我一直在尝试做我的研究。

有什么想法吗?

【问题讨论】:

    标签: zend-framework2 phpunit


    【解决方案1】:

    您收到此错误是因为您直接实例化输入过滤器,然后它不知道您的自定义验证器工厂。

    在实际应用中,InputFilter 使用Zend\Validator\ValidatorPluginManager 从服务管理器获取验证器。

    我看到了解决这个问题的两种方法:

    1.) 您可以从应用程序配置中设置真正的服务管理器,如documentation 中所述,然后从服务管理器中提取输入过滤器:

    $inputFilter = Bootstrap::getServiceManager()->get(\Login\InputFilter\Login::class); // change the service name if you have another
    

    如果你想编写某种集成测试,这个解决方案很好。

    2.) 您可以模拟您的自定义验证器并在 setup 方法中注入 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();
    }
    

    如果你想为登录输入过滤器编写单元测试,这个解决方案很好。

    【讨论】:

    • 感谢您的详细解释。你提到的很有意义,它让我回到了正轨。我添加到您的示例中的唯一内容是 $validator 需要 -&gt;disableOriginalConstructor() 用于模拟对象
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多