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
- Verify the tested code actually throws on the input the test arranges
- Arrange the failing precondition (bad input, missing dependency, etc.) so the exception path is reached
- 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
- Always pair expectExceptionMessage() with an expectException() call and arrange the failing input
- Review expectation-based tests after changing error handling in production code
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
- Failed asserting that exception with message matching "%s" i
- Failed asserting that exception with code "%s" is thrown
- Subscriber "%s" does not implement any known interface - did
- Unknown event type "%s"
- Subscriber "%s" does not implement a known interface
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/813c5463905dec95.
Report an issue: GitHub.