web-dev-qa-db-ja.com

PHPUnitモック-呼び出されたassertメソッド

私は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);
    }        
}

これが私のテストケースです:

public function testExchangeArrayCallsInputFilter(){
    $data = array('id' => 54,
            'name' => 'john',
            'surname' => 'doe',
            'email' => '[email protected]'
    );

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

...そして私は次のエラーを受け取ります:

メソッド名の期待に失敗したのは、1回呼び出されたときと同じです。メソッドは1回呼び出されると予想されていましたが、実際には0回呼び出されました。

どこが間違っているのですか?

12
John Crest

それはすべて、何をテストしたいのか、何をモックしたいのかによって異なります。テストの名前に基づいて、test exchangeArrayメソッドが必要だと思います。

getMockメソッドは、モックしたいメソッドの名前を2番目の引数として取ります。それは彼らが決して呼ばれないことを意味します。

したがって、テストexchangeArrayメソッドとモックgetInputFilterが必要な場合は、次のように2番目の引数に「getInputFilter」を渡す必要があります。

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

ただし、注意してください。モックに何も返さないように指示しなかったため、モックはnull値を返します。つまり、exchangeArrayメソッドの2行目で致命的なエラーが発生します(非オブジェクトでメソッドを呼び出そうとします)。処理するために、偽のフィルターオブジェクトを準備する必要があります。例:

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

また、「実際の」getInputFilterメソッドを呼び出したい場合は、このメソッドをモックすることはできません。

11
Cyprian