Ashley Sheridan​.co.uk

PHPUnit - Testing Core PHP Methods

Posted on

A lot of my focus recently has been outside of PHP so I'm trying to spend some of my personal time working on a personal project. My recent child (code-wise, not my actual child which would go to explain why my time is so lacking the past year) is imogen which is a system built to generate images for email as the email client requests them. My Christmas reading of Clean Code and The Clean Coder game me some focus on the project; I realised that one important thing it was lacking was unit tests.

One problem I encountered with the unit tests, especially given the number of core PHP functions my code used, was testing built-in methods. Typically, you shouldn't test core methods, only the code you've written yourself, but when that code calls core functions and those functions have side effects (of creating imagea, for example) then you likely want to test that the correct method was called but not actually call the method. Luckily, PHP has a weird quirk which can be used to this end.

In PHP, the core methods exist with no namespace. When you call them from namespaced code, the parser first looks for them within the current namespace before falling back to the global namespace that they exist in. What this means is that in unit tests, these methods can be mocked with functions bearing the same name but under the current namespace.

Given the following class and method, we can test that the image was created quite easily without extra testing packages or unnecessary extra code in your application that is just to make testing easier:

<php namespace some\namespace class BaseImageHelper { function create_base_image($width, $height) { return imagecreatetruecolor($width, $height); } }

Now, in our tests, we could let this run through, and pass in some very small values to minimise the memory required, but we could also mock it and never need to do that:

<php namespace some\namespace function imagecreatetruecolor($width, $height) { return "image with width: $width and height: $height"; } class BaseImageHelperTest extends TestCase { public function testGetRealSourcePath() { $test_width = 100; $test_height = 100; $helper = new BaseImageHelper(); $expected_response = "image with width: $test_width and height: $test_height"; $base_image = $helper->create_base_image($test_width, $test_height); $this->assertEquals($base_image, $expected_response); } }

Obviously, this works for testing simple core calls, anything that's a little more complicated is possibly unsuited to this approach. However, it's possibly a sign that your code could be refactored to more closely follow the Single Responsibility Principle and only do one thing, which makes it more testable as a happy side-effect.