2010-09-28 12 views
3

Я работаю над тестом в phpunit, и у меня возникает проблема. У меня есть публичная функция в моем классе, которую я пытаюсь проверить. В зависимости от параметров, переданных методу, защищенная функция также в моем тестовом классе будет вызываться один или два раза. В настоящее время у меня есть тест, чтобы проверить правильность возвращаемых данных, но я также хотел бы убедиться, что защищенный метод называется правильным числом раз.PHPUnit Test Сколько раз вызывается функция

Я знаю, что макет объекта позволяет мне подсчитать количество раз, когда функция вызывается, но она также переопределит значение, возвращаемое защищенной функцией. Я пробовал использовать mock-объект без секции «will», но он просто вернул бы null, а не фактическое значение для защищенного метода.

ExampleClass

public function do_stuff($runTwice){ 
$results = do_cool_stuff(); 
    if($runTwice){ 
    $results = 2 * do_cool_stuff(); 
    } 
    return $results; 
} 

protected function do_cool_stuff() 
{ 
    return 2; 
} 

В моем тесте, я хочу, чтобы проверить, был ли называется do_cool_stuff() один или два раза, но я все равно хочу возвращаемые значения обеих функций, чтобы быть такой же, так что я могу проверить их в качестве хорошо в моем модульном тесте.

tl; dr Я хочу подсчитать количество раз, когда вызывается защищенный метод в моем тестовом объекте (как вы можете сделать с макетным объектом), но я все же хочу, чтобы все методы в моем тестовом методе возвращали их нормальный значения (не как макет объекта).

ответ

1

Попробуйте установить глобальную переменную до использования класса.

$IAmDeclaredOutsideOfTheFunction; 

затем используйте его для хранения счета и просто проверьте его после того, как были вызваны ваши функции и классы.

4

В качестве альтернативы, вернитесь назад, чтобы перевернуть свою собственную тестируемую стенд. Следующий Эйнт довольно, но вы получите идею:

class ExampleClass { 
    public function do_stuff($runTwice) { 
     $results = $this->do_cool_stuff(); 
     if ($runTwice) { 
      $results = 2 * $this->do_cool_stuff(); 
     } 
     return $results; 
    } 

    protected function do_cool_stuff() { 
     return 2; 
    } 
} 

class TestableExampleClass extends ExampleClass { 
    /** Stores how many times the do_cool_stuff method is called */ 
    protected $callCount; 

    function __construct() { 
     $this->callCount = 0; 
    } 

    function getCallCount() { 
     return $this->callCount; 
    } 

    /** Increment the call counter, and then use the base class's functionality */ 
    protected function do_cool_stuff() { 
     $this->callCount++; 
     return parent::do_cool_stuff(); 
    } 
} 


class ExampleClassTest extends PHPUnit_Framework_TestCase { 

    public function test_do_stuff() { 
     $example = new ExampleClass(); 
     $this->assertEquals(2, $example->do_stuff(false)); 
     $this->assertEquals(4, $example->do_stuff(true)); 
    } 

    public function test_do_cool_stuff_is_called_correctly() { 
     // Try it out the first way 
     $firstExample = new TestableExampleClass(); 
     $this->assertEquals(0, $firstExample->getCallCount()); 
     $firstExample->do_stuff(false); 
     $this->assertEquals(1, $firstExample->getCallCount()); 

     // Now test the other code path 
     $secondExample = new TestableExampleClass(); 
     $this->assertEquals(0, $secondExample->getCallCount()); 
     $secondExample->do_stuff(true); 
     $this->assertEquals(2, $secondExample->getCallCount()); 
    } 
} 

Интересно, хотя ли подсчет количества раз защищенный метод, привлекаемыми действительно хороший тест. Это очень сложно сочетать ваш тест с реализацией. Действительно ли имеет значение, называется ли это дважды, или вас больше интересует взаимодействие с другими объектами? Или, возможно, это указывает на то, что do_cool_stuff нуждается в рефакторе на два отдельных метода:

class ExampleClass { 
    public function do_stuff($runTwice) { 
     if ($runTwice) { 
      return $this->do_cool_stuff_twice(); 
     } else { 
      return $this->do_cool_stuff_once(); 
     } 
    } 
    //... 
}