phpunit Assert an Exception is Thrown


Example

PHPUnit provides the following functions to watch for thrown exceptions, which were released with 5.2.0:

  • expectException($exception)
  • expectExceptionMessage($message)
  • expectExceptionCode($code)
  • expectExceptionMessageRegExp($messageRegExp)

These are used to watch for an exception to be thrown and inspect the properties of that exception.

Let's start with a math function that divides (just for simplicity). It will raise an exception if the denominator is zero.

function divide($numerator, $denominator) {
    
    if ($denominator !== 0) {
        return $numerator/$denominator;       
    } else {
        throw new \Exception("Cannot divide by zero", 100);
    }

}

Now for the test code.

class DivideTest extends PHPUnit_Framework_TestCase
{

    public function test_divide() {

        $this->assertSame(2,divide(4,2));

        $this->expectException("Exception");
        $this->expectExceptionCode(100);
        $this->expectExceptionMessage("Cannot divide by zero");
        $this->expectExceptionMessageRegExp('/divide by zero$/');

        // the expectations have been set up, now run the code
        // that should throw the exception
        divide(4,0);

        // The following code will not execute, the method has exited
        $this->assertSame(0,1);

    }

}

The test_divide() function starts by asserting that the function correctly divided 4 by 2 and answered 2. This assertion will pass.

Next, the expectations for the upcoming exception are set. Notice, they are set before the code that will throw the exception. All four assertions are shown for demonstration purposes, but this is normally not necessary.

The divide(4,0) will then throw the expected exception and all the expect* function will pass.

But note that the code $this->assertSame(0,1) will not be executed, the fact that it is a failure doesn't matter, because it will not run. The divide by zero exception causes the test method to exit. This can be a source of confusion while debugging.