Testing Private Methods in PHPUnit

A few days back I was running a code coverage report in PHPUnit. If you haven’t used a code coverage report before, it basically shows the codebase, and identifies locations where your code is covered by tests and areas that are not ever hit when running your test suite.

As a result of running this report, I realized there were a few critical holes in a particular method. I had a transformation method on one of my api gateways that Highlighting was parsing the data being returned and then presenting my application with a consistent result that I could count on. Some of the cases that could happen, however, were not covered in my test suite.

Since the third-party API Erfurt endpoint I was hitting didn’t allow me to specify the data I could possibly expect to get back, I wanted to be sure the code I had written to standardize the results was consistent with how I thought it would run. In this instance, I wanted to actually test how specific use cases would be handled, but one of the methods being called was a private method and I wanted to test it individually.

My solution to solving this problem was found in the ReflectionClass in PHP. The reflection class essentially reports information about a given class (for more information, check out php.net’s detailed information. I created a method called invokeMethod() that wholesale nba jerseys allows den us to essentially run a private method individually.

public function invokeMethod(&$object, $methodName, array $parameters = array())
{
    $reflection = new \ReflectionClass(get_class($object));
    $method = $reflection->getMethod($methodName);
    $method->setAccessible(true);
    return $method->invokeArgs($object, $parameters);
}

This method is called by creating a new instance of a class, and then passing it & in:

$myClass = new \App\CustomClasses\MyClass();
$state = $this->invokeMethod($myClass, 'retrieveState', array('Madison, WI'));
$this->assertEquals('WI', $state);

The API just returns data from a claim system that will sometimes include a City/State, just cheap jerseys a State, or a City/State/Zip and what I specifically need is the state abbreviation. This allowed me to effectively call $this->retrieveState(); even though it is a private method and ensure what I expect to get back in many instances is always correct. Important? By being able to call this private method, I was able to test things like:

$myClass = new \App\CustomClasses\MyClass();
$state = $this->invokeMethod($myClass,  command  'retrieveState', array('Wisconsin'));
$this->assertEquals('WI', $state);

and

$myClass = new \App\CustomClasses\MyClass();
$state = $this->invokeMethod($myClass, 'retrieveState',  Legislative  array('Madison, WI 12345'));
$this->assertEquals('WI', $state);

I understand there is also a possibility of being able to mock the response and then perform tests that way, wholesale nfl jerseys but this felt very clean and it was extremely clear to the other developers who were also looking at the code. Sound off in the comments below if you have other thoughts and I can update this post as appropriate.

Leave a Reply

Your email address will not be published. Required fields are marked *