Обычно вы просто не тестируете и не высмеиваете приватные и защищенные методы напрямую.
То, что вы хотите проверить, - это публичный API вашего класса. Все остальное является деталью реализации для вашего класса и не должно «ломать» ваши тесты, если вы измените его.
Это также поможет вам, когда вы заметите, что «не можете получить 100% покрытие кода», потому что в вашем классе может быть код, который вы не можете выполнить, вызвав общедоступный API.
Обычно вы не хотите этого делать
Но если ваш класс выглядит так:
class a {
public function b() {
return 5 + $this->c();
}
private function c() {
return mt_rand(1,3);
}
}
Я вижу необходимость в макете c (), так как «случайная» функция является глобальным состоянием, и вы не можете это проверить.
Решение "чистый? / Многословный? / Чрезмерно сложный, может быть? / I-like-it-обычно"
class a {
public function __construct(RandomGenerator $foo) {
$this->foo = $foo;
}
public function b() {
return 5 + $this->c();
}
private function c() {
return $this->foo->rand(1,3);
}
}
теперь больше не нужно использовать "c ()", поскольку он не содержит глобальных переменных, и вы можете хорошо тестировать.
Если вы не хотите делать или не можете удалить глобальное состояние из вашей частной функции (плохая вещь плохая реальность или ваше определение плохого может отличаться), которую вы можете проверить на макет .
// maybe set the function protected for this to work
$testMe = $this->getMock("a", array("c"));
$testMe->expects($this->once())->method("c")->will($this->returnValue(123123));
и запустите ваши тесты против этого макета, поскольку единственная функция, которую вы убираете / mock, это "c ()".
Цитировать книгу "Прагматическое модульное тестирование":
"В общем, вы не хотите нарушать инкапсуляцию ради тестирования (или, как говорила мама," не выставляйте своих рядовых! "). В большинстве случаев вы должны иметь возможность протестируйте класс, используя его открытые методы. Если за закрытым или защищенным доступом скрыта значительная функциональность, это может быть предупреждением о том, что существует другой класс, пытающийся выйти из него. "
Еще немного: Why you don't want test private methods.