30 Days of Automated Testing:Using PHPUnit【D12】

Exception Testing

WilliamP
3 min readJan 24, 2023

In previous articles, we have practiced many testing methods, but I wonder if you have noticed that we mostly tested “positive” scenarios and did not test “negative” scenarios, or exception cases.

Can exception cases also be tested? Of course they can!

This article will introduce how to “successfully test failures”.

Exception Testing Functions

$this->expectException()

  • SignatureexpectException(string $exception):
  • Explanation:This function can verify whether the exception class specified in parameter 1 is thrown.

$this->expectExceptionMessage()

  • SignatureexpectExceptionMessage(string $message)
  • Explanation:This function can verify if an exception class has been thrown, and if the exception message includes the string provided in parameter 1.

$this->expectExceptionMessageMatches()

  • SignatureexpectExceptionMessageMatches(string $regularExpression)
  • Explanation:This function is similar to the previous one, the difference is that it will use a regular expression to make the determination.

$this->expectExceptionCode()

  • SignatureexpectExceptionCode($code)
  • Explanation:This function can verify whether an exception class has been thrown and whether the exception code is equal to the first parameter.

Examples

  • app/Services/TestService.php
<?php

namespace App\Services;

use Exception;

class TestService
{
/**
* @throws Exception
*/
public function calculateBmi(float $height, float $weight): float
{
if ($weight <= 0 || $height <= 0) {
throw new Exception('Invalid input!', 1);
}

return $weight / ($height * $height);
}
}

The above code is using the BMI calculation code from a previous example and added the behavior of “throwing an exception when input is not as expected.”

  • tests/Feature/ExceptionTest.php
<?php

namespace Tests\Feature;

use App\Services\TestService;
use Exception;
use Tests\TestCase;

class ExceptionTest extends TestCase
{
/**
* @return void
*/
public function testCanThrowExceptionWhenInvaliHeight()
{
$service = app(TestService::class);

$this->expectException(Exception::class);

$service->calculateBmi(0.0, 1.0);
}

/**
* @return void
*/
public function testCanThrowExceptionWhenInvaliWeight()
{
$service = app(TestService::class);

$this->expectException(Exception::class);

$service->calculateBmi(1.0, 0.0);
}

/**
* @return void
*/
public function testCanThrowExceptionWithMessageWhenInvaliData()
{
$service = app(TestService::class);

$this->expectExceptionMessage('Invalid');


$service->calculateBmi(0.0, 1.0);
}

/**
* @return void
*/
public function testCanThrowExceptionWithMessageRegexMatcchWhenInvaliData()
{
$service = app(TestService::class);

$this->expectExceptionMessageMatches('/Invalid/');

$service->calculateBmi(0.0, 1.0);
}

/**
* @return void
*/
public function testCanThrowExceptionWithCodeWhenInvaliData()
{
$service = app(TestService::class);

$this->expectExceptionCode(1);

$service->calculateBmi(0.0, 1.0);
}
}

The above we have written 5 test cases.

  • The first test case testCanThrowExceptionWhenInvaliHeight() verifies that when an invalid height value is entered, the target function throws an exception.
  • The second test case testCanThrowExceptionWhenInvaliWeight() verifies that when an invalid weight value is entered, the target function throws an exception.
  • The third test case testCanThrowExceptionWithMessageWhenInvaliData() verifies that when an invalid height value is entered, the target function throws an exception that includes the specified exception message.
  • The fourth test case testCanThrowExceptionWithMessageRegexMatcchWhenInvaliData() verifies that when an invalid weight value is entered, the target function throws an exception that has an exception message that matches the specified Regex form.
  • The fifth test case testCanThrowExceptionWithCodeWhenInvaliData() verifies that when an invalid weight value is entered, the target function throws an exception that has the same exception code as expected.

In the above, we have finished today’s practice. I hope it has been helpful in understanding exception testing.

Next, we will take a look at PHPUnit’s Annotation!

If you liked this article or found it helpful, feel free to give it some claps and follow the author!

Reference

Articles of This Series

--

--