Access private methods via ReflectionMethod for edge cases — prefer testing through the public API.
Testing Private Methods
// Generally: test behavior, not implementation
// If private methods are complex, they may need extracting
class Calculator {
private function validateInput(int $n): void {
if ($n < 0) throw new InvalidArgumentException("Must be positive");
}
public function factorial(int $n): int {
$this->validateInput($n);
return $n <= 1 ? 1 : $n * $this->factorial($n - 1);
}
}
// Test THROUGH the public method
public function testFactorialValidatesInput(): void {
$this->expectException(InvalidArgumentException::class);
(new Calculator)->factorial(-1);
}
// Access private via Reflection (when necessary)
public function testPrivateMethod(): void {
$calc = new Calculator();
$method = new ReflectionMethod($calc, "validateInput");
// PHP 8.1+ — no need for setAccessible(true)
$method->setAccessible(true);
$this->expectException(InvalidArgumentException::class);
$method->invoke($calc, -5);
}