w3resource

Writing Tests for PHPUnit (Exceptions and Errors)

Introduction

#Testing Exceptions

PHPUnit has a nice way of testing exceptions, using the exceptException() method. The example below illustrates the use of the exceptException() method to test for an exception against a code under test.

<?php
use PHPUnit\Framework\TestCase;

class ExceptionTest extends TestCase
{
    public function testException()
    {
        $this->expectException(InvalidArgumentException::class);
    }
}
?>

When the test for an exception runs, output as shown below is seen

$ phpunit ExceptionTest
PHPUnit |version|.0 by Sebastian Bergmann and contributors.

F

Time: 0 seconds, Memory: 4.75Mb

There was 1 failure:

1) ExceptionTest::testException
Failed asserting that exception of type "InvalidArgumentException" is thrown.

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

There are other exception methods available for use in when writing PHPUnit tests aside the expectException() method, some of these methods are the expectExceptionCode() method, expectExceptionMessage() method, and expectExceptionMessageRegExp() method. These methods are used to set up expectations for exceptions raised by the code under test.

It should be noted that expectExceptionMessage() method asserts that the $actual message contains the $expected message. It doesn’t perform an exact string comparison.

Alternatively, we can also use the @expectedException()@expectedExceptionCode(), @expectedExceptionMessage(), and @expectedExceptionMessageRegExp() annotations to set up expectations for exceptions raised by the code under test. The example below illustrates the use of some of these methods.

Example Using the @expectedException annotation

<?php
use PHPUnit\Framework\TestCase;

class ExceptionTest extends TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testException()
    {
    }
}
?>

When the test using the @expectedException annotation runs, the following output is generated.

$ phpunit ExceptionTest
PHPUnit |version|.0 by Sebastian Bergmann and contributors.

F

Time: 0 seconds, Memory: 4.75Mb

There was 1 failure:

1) ExceptionTest::testException
Failed asserting that exception of type "InvalidArgumentException" is thrown.

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

#Testing PHP Errors

By default, PHPUnit converts PHP errors, warnings, and notices that are triggered during the execution of a test to an exception. Using these exceptions, we  can, for instance, expect a test to trigger a PHP error.

We should note that PHP’s error_reporting runtime configuration can limit which errors PHPUnit will convert to exceptions.

When testing for errors, ensure that the error you are testing for isn’t suppressed by the settings in the PHP error configuration.

The example  below illustrates the testing for PHP errors using @expectedException annotation.

<?php
use PHPUnit\Framework\TestCase;

class ExpectedErrorTest extends TestCase
{
    /**
     * @expectedException PHPUnit\Framework\Error\Error
     */
    public function testFailingInclude()
    {
        include 'not_existing_file.php';
    }
}
?>

When the above test executes, the output below is seen

$ phpunit -d error_reporting=2 ExpectedErrorTest
PHPUnit |version|.0 by Sebastian Bergmann and contributors.

.

Time: 0 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)

PHPUnit\Framework\Error\Notice and PHPUnit\Framework\Error\Warning represent PHP notices and warnings, respectively.

We should note that tests for exceptions should be as specific as possible. Testing for classes that are too generic might lead to undesirable side-effects.

Also testing the Exception class with the @expectedException annotation and expectedException method is no longer permitted.

Some tests that relies on PHP functions to trigger errors like fopen it may sometimes be useful to use error suppression in such tests. This allows us to check the return values by suppressing notices that could lead to a PHPUnit PHPUnit\Framework\Error\Notice.

The example below illustrates a test for return values of codes that uses PHP Errors.

<?php
use PHPUnit\Framework\TestCase;

class ErrorSuppressionTest extends TestCase
{
    public function testFileWriting()
    {
        $writer = new FileWriter;

        $this->assertFalse(@$writer->write('/is-not-writeable/file', 'stuff'));
    }
}

class FileWriter
{
    public function write($file, $content)
    {
        $file = fopen($file, 'w');

        if ($file == false) {
            return false;
        }

        // ...
    }
}
?>

The out of the test above is shown below

$ phpunit ErrorSuppressionTest
PHPUnit |version|.0 by Sebastian Bergmann and contributors.

.

Time: 1 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)

If error suppression was not used in the above test, the test would fail reporting fopen(/is-not-writeable/file): failed to open stream: No such file or directory.

Previous: Writing tests for phpunit (outputs)
Next: The command-line test runner (1)



Follow us on Facebook and Twitter for latest update.