sebastianbergmann/phpunit · error · AssertionFailedError

Failed asserting that exception with message %s "%s" is thro

Error message

Failed asserting that exception with message %s "%s" is thrown

What it means

Thrown by ExceptionExpectation::assertWasRaised() when the test set expectExceptionMessage() (or expectExceptionMessageMatches-like message constraint) but no exception was raised during the test at all. Because assertWasRaised() only runs when nothing was thrown, it cannot compare a message and fails immediately with 'is' for exact or 'containing' for substring expectations.

Source

Thrown at src/Framework/TestCase/ExceptionExpectation.php:153

                ),
            );
        }
    }

    /**
     * @throws AssertionFailedError
     */
    public function assertWasRaised(TestCase $test): void
    {
        if ($this->expectedException !== null) {
            Assert::assertThat(
                null,
                new ExceptionConstraint($this->expectedException),
            );
        } elseif ($this->expectedMessageConstraint !== null) {
            $test->addToAssertionCount(1);

            throw new AssertionFailedError(
                sprintf(
                    'Failed asserting that exception with message %s "%s" is thrown',
                    $this->expectedMessageConstraint instanceof ExceptionMessageIs ? 'is' : 'containing',
                    $this->expectedMessage,
                ),
            );
        } elseif ($this->expectedMessageRegularExpression !== null) {
            $test->addToAssertionCount(1);

            throw new AssertionFailedError(
                sprintf(
                    'Failed asserting that exception with message matching "%s" is thrown',
                    $this->expectedMessageRegularExpression,
                ),
            );
        } elseif ($this->expectedCode !== null) {
            $test->addToAssertionCount(1);

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Verify the tested code actually throws on the input the test arranges
  2. Arrange the failing precondition (bad input, missing dependency, etc.) so the exception path is reached
  3. If the behavior intentionally no longer throws, delete the expectExceptionMessage() call and assert the successful result instead

Example fix

// before
$this->expectExceptionMessage('Division by zero');
$calc->divide(10, 2); // valid input, no exception thrown

// after
$this->expectExceptionMessage('Division by zero');
$calc->divide(10, 0);
Defensive patterns

Strategy: validation

Validate before calling

// Inside the test, make the throwing path explicit so a silent pass is impossible:
self::assertTrue(
    method_exists($calc, 'divide'),
    'precondition: method under test exists',
);
$this->expectExceptionMessage('Division by zero');
$calc->divide(10, 0);

Prevention

When it happens

Trigger: Calling $this->expectExceptionMessage('...') without the code under test throwing any exception; expectExceptionMessage() used alone (no expectException()) and the happy path completes normally.

Common situations: Code fixed so the exception no longer occurs while the test still expects one; exception thrown only under a condition the test no longer arranges; expectExceptionMessage() set before a code path that silently succeeds.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/813c5463905dec95. Report an issue: GitHub.