Тест PHPUnit Сколько раз вызывается функция

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

Я знаю, что макет объекта позволит мне подсчитать количество раз, когда функция вызывается, но она также переопределит значение, возвращаемое защищенной функцией. Я пробовал использовать 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 Я хочу подсчитать количество раз, когда вызывается защищенный метод в моем тестовом объекте (например, вы можете сделать с макетным объектом), но я все же хочу, чтобы все методы в моем тестовом методе возвращали свои нормальные значения (не как макет объекта).

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

 $IAmDeclaredOutsideOfTheFunction; 

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

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

 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(); } } //... }