Phpunit: Custom exception assertions

Created on 21 Feb 2019  路  2Comments  路  Source: sebastianbergmann/phpunit

PHPUnit currently offers no extension point for implementing custom exception assertions. Before proposing #3537, we tried to implement a custom assertion for that but we quickly come across the fact that the current design does not offer such flexibility.

Besides #3537, there are other cases where custom exception assertions are useful, for example:

interface EvaluationException extends \Throwable {
    public function getNode() : Node;
}

interface UnexpectedResultException extends \Throwable {
    public function getDeviation() : float;
}

public function testExceptionCause() : void
{
    $this->expectException(OperationFailedException::class);

    try {
        SomeOperationAction::execute();
    } catch (UnexpectedResultException $exception) {
        self::assertEquals(1.5, $exception->getDeviation());

        throw $exception;
    }
}

The idea consists of adding a new method expectExceptionThat(Constraint $constraint): void to TestCase, that will keep an ordered list of constraints to be evaluated when the test runs. Additionally, it allows us to refactor the test case to take advantage of the new mechanism for performing exception-related assertions:

Before:

public function expectException(string $exception): void
{
     $this->expectedException = $exception;
}

if ($this->expectedException !== null) {
     $this->assertThat(
          $exception,
          new ExceptionConstraint(
               $this->expectedException
          )
     );
}

After:

public function expectException(string $exception): void
{
     $this->assertExceptionThat(
          new ExceptionConstraint(
               $exception
          )
     );
}

Now, we can write custom contraints or reuse the existing ones to perform assertion against exceptions:

public function testExceptionCause() : void
{
     $this->expectException(EvaluationException::class);

     // Custom constraint
     $this->expectExceptionThat(self::nodeIsEqual($node));

     // Alternatively
     $this->expectExceptionThat(
          self::callback(function (EvaluationException $exception) use ($node) : bool {
               return $node->equals($exception->getNode());
          })
     );
}

I'd be glad to provide a PR if welcome :)

All 2 comments

Sorry to say that, but I do not see much value in this.

You're the boss :)

Was this page helpful?
0 / 5 - 0 ratings