If you work on unit testing, sooner or later you will face this dilemma
TL;DR: Don't test your private methods.
Problems
Breaking Encapsulation
Code Duplication
Solutions
If your method is simple, you don't need to test it.
If your method is complicated, you need to convert it into a Method Object.
Do not make your methods public for testing.
Do not use metaprogramming to avoid protection.
Do not move the private computation to helpers.
Do not use static methods for computations.
Context
We test our classes and methods.
At some point, we rely on auxiliary computations and we need to test them in a white-box way.
Sample Code
Wrong
<?
final class Star {
private $distanceInParsecs;
public function timeToReachLightToUs() {
return $this->convertDistanceInParsecsToLightYears($this->distanceInParsecs);
}
private function convertDistanceInParsecsToLightYears($distanceInParsecs) {
return 3.26 * $distanceInParsecs;
//function is using an argument which is already available.
//since it has private access to $distanceInParsecs
//this is another smell indicator.
//We cannot test this function since it is private
}
}
Right
<?
final class Star {
private $distanceInParsecs;
public function timeToReachLightToUs() {
return new ParsecsToLightYearsConverter($this->distanceInParsecs);
}
}
final class ParsecsToLightYearsConverter {
public function convert($distanceInParsecs) {
return 3.26 * $distanceInParsecs;
}
}
final class ParsecsToLightYearsConverterTest extends TestCase {