Search code examples
phpunit-testingphpunit

Best practices to test protected methods with PHPUnit


I found the discussion on Do you test private method informative.

I have decided, that in some classes, I want to have protected methods, but test them. Some of these methods are static and short. Because most of the public methods make use of them, I will probably be able to safely remove the tests later. But for starting with a TDD approach and avoid debugging, I really want to test them.

I thought of the following:

  • Method Object as adviced in an answer seems to be overkill for this.
  • Start with public methods and when code coverage is given by higher level tests, turn them protected and remove the tests.
  • Inherit a class with a testable interface making protected methods public

Which is best practice? Is there anything else?

It seems, that JUnit automatically changes protected methods to be public, but I did not have a deeper look at it. PHP does not allow this via reflection.


Solution

  • If you're using PHP5 (>= 5.3.2) with PHPUnit, you can test your private and protected methods by using reflection to set them to be public prior to running your tests:

    protected static function getMethod($name) {
      $class = new ReflectionClass('MyClass');
      $method = $class->getMethod($name);
      // $method->setAccessible(true); // Use this if you are running PHP older than 8.1.0
      return $method;
    }
    
    public function testFoo() {
      $foo = self::getMethod('foo');
      $obj = new MyClass();
      $foo->invokeArgs($obj, array(...));
      ...
    }