Testing protected methods with PHP

Testing private and protected methods in PHP isn’t a trivial task. Consider a very simple class:

class Foo {
  protected function _echo($str) {
    return $str;
  }
}

A simple test case written for PHPUnit would check to ensure that the _echo method will return the string passed to it as input:

class fooTest extends PHPUnit_Framework_TestCase {
  public function test_echo () {
    $obj = new Foo();
    $this->assertEquals('test', $obj->_echo('test'));
  }
}

But when the test runs, the result is fairly predictable:

Fatal error: Call to protected method Foo::_echo() from context 'fooTest'

Since version 5.3.2, however, PHP’s ReflectionMethod class makes it possible to temporarily work around access modifiers. The magic is in the setAccessible method, and it looks like this:

$method = new ReflectionMethod('Foo', '_echo');
$method->setAccessible(true);

Generalizing and adding reflection to the test case allows protected methods to be called within individual tests:

class fooTest extends PHPUnit_Framework_TestCase {

    protected function run_protected_method ($obj, $method, $args = array()) {
      $method = new ReflectionMethod(get_class($obj), $method);
      $method->setAccessible(true);
      return $method->invokeArgs($obj, $args);
    }

  public function test_echo () {
    $obj = new Foo();
    $result = $this->run_protected_method($obj, '_echo', array('test'));
    $this->assertEquals('test', $result);
  }
}

The test runs much better now:

PHPUnit 3.5.14 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 3.00Mb
OK (1 test, 1 assertion)

Let’s keep in touch

Reach out on Twitter or subscribe for (very) occasional updates.

Hey, I'm RJ: digital entomologist and intermittent micropoet, writing from the beautiful Rose City.