sebastianbergmann/phpunit · error · ExpectationFailedException
Expected deprecation with message "%s" was not triggered
Error message
Expected deprecation with message "%s" was not triggered
What it means
Thrown after the test body finishes when expectDeprecation() was called but DeprecationCollector never recorded a matching user deprecation. PHPUnit verifies outstanding deprecation expectations in verifyDeprecationExpectations() during runBare(), so a missing deprecation is treated as a failed assertion.
Source
Thrown at src/Framework/TestCase.php:1505
$this->errorLogCapture->stop();
}
$this->emitEventForCustomTestMethodInvocation();
$this->exceptionExpectation->assertWasRaised($this);
return $testResult;
}
/**
* @throws ExpectationFailedException
*/
private function verifyDeprecationExpectations(): void
{
foreach ($this->expectedUserDeprecationMessage as $deprecationExpectation) {
$this->numberOfAssertionsPerformed++;
if (!in_array($deprecationExpectation, DeprecationCollector::deprecations(), true)) {
throw new ExpectationFailedException(
sprintf(
'Expected deprecation with message "%s" was not triggered',
$deprecationExpectation,
),
);
}
}
foreach ($this->expectedUserDeprecationMessageRegularExpression as $deprecationExpectation) {
$this->numberOfAssertionsPerformed++;
$expectedDeprecationTriggered = array_any(
DeprecationCollector::deprecations(),
static fn (string $deprecation) => @preg_match($deprecationExpectation, $deprecation) > 0,
);
if (!$expectedDeprecationTriggered) {
throw new ExpectationFailedException(View on GitHub (pinned to f123cdb2a2)
Solutions
- Verify the code under test actually executes the branch that triggers the deprecation in this test
- Compare the expected string byte-for-byte with the trigger_error() message; fix typos or interpolated values
- Switch to expectDeprecationMatch() with a regex when the message contains variable parts
- Ensure the deprecation is triggered in the same PHP process (avoid process isolation for this test)
Example fix
// before
$this->expectDeprecation('Using Config v2 is deprecated');
$api->load("v3"); // never touches the deprecated v2 path
// after
$this->expectDeprecation('Using Config v2 is deprecated');
$api->load("v2"); // exercises the deprecated path Defensive patterns
Strategy: validation
Validate before calling
// Before the test: confirm the expected deprecation is among collected ones in this process
$this->expectDeprecation('Config v2 is deprecated');
$api->load('v2');
self::assertContains(
'Config v2 is deprecated',
DeprecationCollector::deprecations(),
); Try / catch
// When wrapping third-party tests, let the failure surface instead of swallowing it:
try {
$test->runBare();
} catch (ExpectationFailedException $e) {
if (!str_contains($e->getMessage(), 'Expected deprecation with message')) {
throw $e;
}
// record as deprecation-missing failure
} Prevention
- Copy the deprecation string from the trigger_error() call, not from memory
- Use expectDeprecationMatch() whenever the message has variable parts
- Do not enable process isolation for tests that assert deprecations
When it happens
Trigger: Calling $this->expectDeprecation('exact message') but the code under test never calls trigger_error($msg, E_USER_DEPRECATED) with exactly that message, or the deprecation fires in a separate process from the one collecting them.
Common situations: Message typos or dynamic parts in the deprecation string (use expectDeprecationMatch() for those); the deprecated code path not being reached by this test; process isolation splitting the collector; library versions changing deprecation wording.
Related errors
- Expected deprecation with message matching regular expressio
- Class or interface "%s" does not exist
- File "%s" does not exist
- Invalid expected exception message regular expression given:
- Passing an argument of type Generator for the %s parameter i
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/d7af430359cb5d4c.
Report an issue: GitHub.