PHPUnit模拟 - 调用assert方法

Joh*_*est 10 methods phpunit mocking

我是phpunit的新手并且已经阅读了关于模拟对象的文档,但目前还不是很清楚.

我正在尝试编写一个简单的测试,在类中调用断言方法.使用以下代码,我测试当调用Client :: exchangeArray时,调用Client :: getInputFilter.

class Client implements InputFilterAwareInterface
{

public function getInputFilter() {
    if(!$this->_inputFilter){
        $inputFactory = new InputFactory();
        $inputFilter = new InputFilter();

        $inputFilter->add($inputFactory->createInput(array(
            'name' => 'id',
            'required' => true,
            'filters' => array(
                array(
                    'name' => 'Int'
                )
            )
        )));

        $inputFilter->add($inputFactory->createInput(array(
            'name' => 'name',
            'required' => true,
            'filters' => array(
                array(
                    'name' => 'StripTags'
                ),
                array(
                    'name' => 'StringTrim'
                ),
                array(
                     'name' => 'StripNewLines'      
                ),
                array(
                    'name' => 'Alpha'
                )
            ),
            'validators' => array(
                array(
                    'name' => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min' => 2,
                        'max' => 100
                    )
                )
            )
        )));

        $inputFilter->add($inputFactory->createInput(array(
            'name' => 'surname',
            'required' => true,
            'filters' => array(
                array(
                    'name' => 'StripTags'
                ),
                array(
                    'name' => 'StringTrim'
                )
            ),
            'validators' => array(
                array(
                    'name' => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min' => 2,
                        'max' => 100
                    )
                )
            )
        )));

        $inputFilter->add($inputFactory->createInput(array(
            'name' => 'email',
            'required' => false,
            'filters' => array(
                array(
                    'name' => 'StripTags'
                ),
                array(
                    'name' => 'StringTrim'
                )
            ),
            'validators' => array(
                array(
                    'name' => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min' => 2,
                        'max' => 150
                    )
                ),
                array(
                    'name' => 'EmailAddress'
                )
            )
        )));

        $this->_inputFilter = $inputFilter;
    }
    return $this->_inputFilter;
}

public function exchangeArray($data){
    $inputFilter = $this->getInputFilter();
    $inputFilter->setData($data);
    if(!$inputFilter->isValid()){
        throw new \Exception('Invalid client data'); 
    }

    $cleanValues = $inputFilter->getValues();

    $this->_id = (isset($cleanValues['id']) ? $cleanValues['id'] : null);
    $this->_name = (isset($cleanValues['name']) ? $cleanValues['name'] : null);
    $this->_surname = (isset($cleanValues['surname']) ? $cleanValues['surname'] : null);
    $this->_email = (isset($cleanValues['email']) ? $cleanValues['email'] : null);
    }        
}
Run Code Online (Sandbox Code Playgroud)

这是我的测试用例:

public function testExchangeArrayCallsInputFilter(){
    $data = array('id' => 54,
            'name' => 'john',
            'surname' => 'doe',
            'email' => 'john.doe@domain.com'
    );

    $mock = $this->getMock('Client', array('exchangeArray'));
    $mock->expects($this->once())
         ->method('getInputFilter');
    $mock->exchangeArray($data);
}
Run Code Online (Sandbox Code Playgroud)

...而且我收到以下错误:

方法名称的期望失败等于1次调用时.预计方法被调用1次,实际上被称为0次.

我哪里错了?

Cyp*_*ian 12

这一切都取决于你想要测试什么以及你想要什么模拟.根据您的测试名称,我假设您需要测试exchangeArray方法.

getMock方法将您想要模拟的方法的名称作为第二个参数.这意味着他们永远不会被召唤.

所以,如果你想要测试exchangeArray方法和mock,getInputFilter你应该在第二个参数中传递"getInputFilter",如下所示:

$mock = $this->getMock('Client', array('getInputFilter'));
$mock->expects($this->once())
     ->method('getInputFilter');
$mock->exchangeArray($data);
Run Code Online (Sandbox Code Playgroud)

不过要小心.你没有告诉你的mock返回任何东西,所以它将返回null值.这意味着你将在第二行exchangeArray方法上遇到致命错误(试图在非对象上调用方法).你应该准备一些伪造的过滤器对象来处理,例如:

// $preparedFilterObject = ...
$mock = $this->getMock('Client', array('getInputFilter'));
$mock->expects($this->once())
    ->method('getInputFilter')
    ->will($this->returnValue($preparedFilterObject);
$mock->exchangeArray($data);
Run Code Online (Sandbox Code Playgroud)

如果你想调用"真正的" getInputFilter方法 - 那么你就是不能模仿这种方法.