2013-12-24 2 views
1

Я пишу PHPUnit модульных тестов для этого класса Zend Framework 2:Как unit-test абстрактный класс, когда его конструктор выполняет свой абстрактный метод (-s)?

<?php 
namespace MyNamespace\InputFilter; 

use Zend\InputFilter\Input as ZendInput; 
use Zend\InputFilter\Factory; 
use Zend\InputFilter\InputInterface; 
use MyNamespace\Exception\InvalidParameterException; 

abstract class AbstractInput extends ZendInput 
{ 
    final public function __construct() 
    { 
     // The constructor uses/executes the abstract method getInputSpecification(). 
     $this->init($this->getInputSpecification()); 
    } 
    public function merge(InputInterface $input) 
    { 
     $mergedInput = parent::merge($input); 
     $mergedInput->setFallbackValue($input->getFallbackValue()); 
     return $mergedInput; 
    } 
    public function isValid() 
    { 
     $this->injectNotEmptyValidator(); 
     $validator = $this->getValidatorChain(); 
     $value  = $this->getValue(); 
     $result = $validator->isValid($value, $context); 
     return $result; 
    } 
    protected function init($inputSpecification) 
    { 
     $factory = new Factory(); 
     $tempInput = $factory->createInput($inputSpecification); 
     $this->merge($tempInput); 
    } 
    abstract protected function getInputSpecification(); 
    public function getFinalValue($param) 
    { 
     $finalValue = null; 
     if (empty($param) || $this->getValue() === '') { 
      if ($this->getFallbackValue() !== null) { 
       $finalValue = $this->getFallbackValue(); 
      } else { 
       throw new InvalidParameterException('The parameter ' . $this->name . ' must be set!'); 
      } 
     } else { 
      if ($this->isValid()) { 
       $finalValue = $this->getValue(); 
      } else { 
       throw new InvalidParameterException('The parameter ' . $this->name . ' is invalid!'); 
      } 
     } 
     return $finalValue; 
    } 
} 

и получить проблемы с этим. Этот код

// ... 
class AbstractInputTest extends TestCase 
{ 
    // ... 
    public function setUp() 
    { 
     $stub = $this->getMockForAbstractClass('\MyNamespace\InputFilter\AbstractInput'); 
     $stub 
      ->expects($this->any()) 
      ->method('getInputSpecification') 
      ->will($this->returnValue(array()) 
     ); 
     // ... 
    } 
    // ... 
} 

вызывает ошибку:

$ phpunit SgtrTest/InputFilter/AbstractInputTest.php PHPUnit 3.7.21 by Sebastian Bergmann.

Configuration read from /path/to/project/tests/phpunit.xml

E...

Time: 1 second, Memory: 7,00Mb

There was 1 error:

1) SgtrTest\InputFilter\AbstractInputTest::testMerge Zend\InputFilter\Exception\InvalidArgumentException: Zend\InputFilter\Factory::createInput expects an array or Traversable; received "NULL"

/path/to/project/vendor/ZF2/library/Zend/InputFilter/Factory.php:98 /path/to/project/vendor/SGTR/library/MyNamespace/InputFilter/AbstractInput.php:72 /path/to/project/vendor/SGTR/library/MyNamespace/InputFilter/AbstractInput.php:31 /path/to/project/tests/SgtrTest/InputFilter/AbstractInputTest.php:20

FAILURES! Tests: 4, Assertions: 0, Errors: 1.

Я undestand, почему выкинули ошибка. Бу как решить это по-другому?

+1

Единица тестирования конкретных классов, которые продлевают ваш реферат .... не то, что это класс с абстрактными методами, а не абстрактным классом –

+1

Спасибо за ваш комментарий. Но разве не нужно тестировать абстрактные классы? ОК, абстрактные классы содержат также конкретные методы - и они должны быть протестированы - непосредственно в тестовых классах класса, а не в тестовых классах подклассов. Например. ['ZendTest \ Cache \ Storage \ Adapter \ AbstractAdapter'] (https://github.com/zendframework/zf2/blob/master/tests/ZendTest/Cache/Storage/Adapter/AbstractAdapterTest.php) – automatix

ответ

1

В моем тесте я создаю быстрый класс, расширяющий абстрактный класс, затем я тестирую конкретные методы в этом классе.

class TestAbstractInput extends AbstractInput 
{ 
    ... 
} 

class AbstractInputTest extends TestCase 
{ 
    // ... 
    public function setUp() 
    { 
     $this->TestClassObject = new TestAbstractInput(); 
    } 

    public function test_isValid() 
    { 
     $this->assertEquals(1, $this->TestClassObject->isValid); 
    } 
} 

После этого, вы можете использовать либо Mock объект абстрактного класса, созданного в тесте, или издеваться абстрактный класс, как вы сделали.

+0

Я думаю, что a хороший обходной путь. Придется попробовать. Спасибо! – automatix

+0

Это работало для вас? Если да, можете ли вы принять ответ для других, чтобы увидеть, или я могу помочь, предоставив дополнительную информацию? –

Смежные вопросы