Matthew Daly's Blog

I'm a web developer in Norfolk. This is my blog...

16th November 2017 3:15 pm

Creating Custom Assertions With Phpunit

Today I’ve been working on a library I’m building for making it easier to build RESTful API’s with Laravel. It uses an abstract RESTful controller, which inherits from the default Laravel controller, and I wanted to verify that the instantiated controller includes all the traits from the base controller.

However, there was a problem. The only practical way to verify that a class includes a trait is with the class_uses() function, but this doesn’t work if the class inherits from a parent that includes these traits. As the class is abstract, it can’t be instantiated directly, so you must either create a dummy class just for testing that extends it, or mock the class, and that means that class_uses() won’t work. As a result, I needed to first get the parent class, then call class_uses() on that, which is possible, but a bit verbose to do repeatedly for several tests.

Fortunately it’s quite easy to create your own custom assertions in PHPUnit. I started out by setting up the test with the assertion I wanted to have:

<?php
namespace Tests\Unit\Http\Controllers;
use Tests\TestCase;
use Mockery as m;
class RestfulControllerTest extends TestCase
{
public function testTraits()
{
$controller = m::mock('Matthewbdaly\Harmony\Http\Controllers\RestfulController')->makePartial();
$this->assertParentHasTrait('Illuminate\Foundation\Bus\DispatchesJobs', $controller);
$this->assertParentHasTrait('Illuminate\Foundation\Validation\ValidatesRequests', $controller);
$this->assertParentHasTrait('Illuminate\Foundation\Auth\Access\AuthorizesRequests', $controller);
}
}

Actually implementing the assertion is fairly straightforward. You simply add the assertion as a method on the base test case you’re using. and accept whatever arguments are required, plus a final argument of $message = ''. Then you call self::assertThat(), as demonstrated below:

public function assertParentHasTrait($trait, $class, $message = '')
{
$parent = get_parent_class($class);
$traits = class_uses($parent);
self::assertThat(in_array($trait, $traits), self::isTrue(), $message);
}

In this case we’re asserting that the specified trait appears in the list of traits on the parent class. Note the use of self::isTrue() - this just verifies that the response is truthy.

Using this method it’s quite easy to create custom assertions, which can help make your tests less verbose and easier to read.

Recent Posts

Full Text Search With Laravel and Postgresql

Building a Postcode Lookup Client With Httplug and Phpspec

Creating Custom Assertions With Phpunit

Catching Debug Statements in PHP

An Azure Filesystem Integration for Laravel

About me

I'm a web and mobile app developer based in Norfolk. My skillset includes Python, PHP and Javascript, and I have extensive experience working with CodeIgniter, Laravel, Django, Phonegap and Angular.js.