Вам не надо тестировать приватные методы.
Но как же тогда быть, вы скажете?
Публичные методы используют эти приватные методы, так и проходит тестирование.
Из этого вытекает, что класс должен быть небольшим и выполнять только одну задачу. Поэтому его приватные методы будут всегда задействованы при тестировании публичных.
Но вы скажете, что у вас там в публичных методах обращения к базе данных и внешним API, как же тут быть?
А быть тут просто: все зависимости вашего класса должны включаться в качестве аргументов конструктора, и через использование интерфейсов в аргументах. (Dependency Injection)
Таким образом в тесте все зависимости класса заменяются теми же моками, и вы легко тестируете не просто сферического корня в вакууме (приватный метод), а именно то, что и нужно тестировать: функциональность самого класса, а не его частей, потому что в OOP именно класс является как бы атомом функционала.
Но... если вам всё же таки очень надо, то можно это сделать при помощи рефлексии:
Хорошей практикой является использовать всегда protected вместо private.
Пишете себе такую вот утилиту:
class PHPUnitUtil
{
public static function callMethod($obj, $name, array $args) {
$class = new \ReflectionClass($obj);
$method = $class->getMethod($name);
// $method->setAccessible(true); // если PHP старше 8.1.0
return $method->invokeArgs($obj, $args);
}
}
И используете ее в тестах
$returnVal = PHPUnitUtil::callMethod(
$this->object,
'_nameOfProtectedMethod',
array($arg1, $arg2)
);
Есть ещё вариант.
// Оригинальный класс
class Foo {
protected function stuff() {
// secret stuff, you want to test
}
}
// Класс для тестов
class SubFoo extends Foo {
public function exposedStuff() {
return $this->stuff();
}
}