symfony/phpunit-bridge
Symfony PHPUnit Bridge adds utilities around PHPUnit, with a focus on managing and asserting deprecation notices for smoother upgrades. It helps track, filter, and report deprecations during test runs, making CI output cleaner and migrations safer.
Installation: Add the package via Composer in your Laravel project:
composer require symfony/phpunit-bridge
Ensure phpunit/phpunit is also installed (Laravel includes it by default).
First Use Case:
Extend Laravel’s default TestCase to leverage deprecation utilities:
use Symfony\Bridge\PhpUnit\ClockMock;
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class MyTestCase extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
}
Where to Look First:
vendor/symfony/phpunit-bridge/ for source code (e.g., ClockMock, ExpectUserDeprecationMessageTrait).phpunit.xml to configure PHPUnit behavior (e.g., deprecation flags).Use ExpectUserDeprecationMessageTrait to assert deprecation notices in tests:
public function testDeprecationNotice()
{
$this->expectUserDeprecationMessage('Deprecated feature: use X instead of Y');
// Trigger deprecated code
SomeDeprecatedClass::oldMethod();
}
ClockMockReplace DateTime or time() calls in tests:
public function testTimeDependentLogic()
{
$clock = new ClockMock('2023-01-01');
$this->setClock($clock);
$this->assertEquals('2023-01-01', (new DateTime())->format('Y-m-d'));
}
Override Laravel’s TestCase to include Symfony utilities:
// tests/TestCase.php
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
abstract class TestCase extends \Illuminate\Foundation\Testing\TestCase
{
use ExpectUserDeprecationMessageTrait;
}
Configure PHPUnit to fail on deprecation warnings in phpunit.xml:
<phpunit>
<php>
<ini name="error_reporting" value="-1" />
</php>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory>./app</directory>
</whitelist>
</filter>
<extensions>
<extension class="Symfony\Bridge\PhpUnit\DeprecationExtension" />
</extensions>
</phpunit>
Combine with Laravel’s data providers for bulk deprecation checks:
public function deprecationDataProvider()
{
return [
['method1', 'Deprecated message 1'],
['method2', 'Deprecated message 2'],
];
}
/**
* @dataProvider deprecationDataProvider
*/
public function testDeprecationMessages($method, $message)
{
$this->expectUserDeprecationMessage($message);
SomeClass::$method();
}
Service Container Mocking:
Use ClockMock to freeze time in API tests:
public function testTimeBasedRateLimiting()
{
$clock = new ClockMock('2023-01-01T00:00:00');
$this->app->instance(\DateTimeInterface::class, $clock);
// Test rate-limiting logic
}
Artisan Command Testing: Mock time for scheduled commands:
public function testScheduledCommand()
{
$clock = new ClockMock('2023-01-01T08:00:00');
$this->app->instance(\DateTimeInterface::class, $clock);
$this->artisan('command:run')->assertExitCode(0);
}
Database Seeders:
Use ClockMock to test time-sensitive seeders:
public function testTimeBasedSeeder()
{
$clock = new ClockMock('2023-01-01');
$this->app->instance(\DateTimeInterface::class, $clock);
Artisan::call('db:seed', ['--class' => 'TimeBasedSeeder']);
}
PHPUnit Version Conflicts:
bootstrap: false in phpunit.xml to avoid conflicts:
<phpunit bootstrap="false">
phpunit.xml or use symfony/phpunit-bridge:^7.4 for PHPUnit 10+.Deprecation Message Mismatches:
expectUserDeprecationMessage() is strict about message content.$this->expectUserDeprecationMessage('/Deprecated: .*/');
ClockMock Scope:
ClockMock only affects DateTime/DateTimeImmutable instances created after setup.$this->setClock(new ClockMock('2023-01-02'));
$newDateTime = new DateTime(); // Uses new clock time
Laravel Service Provider Conflicts:
DateTimeInterface in the container may conflict with ClockMock.ClockMock explicitly in tests:
$this->app->bind(\DateTimeInterface::class, function () {
return new ClockMock('2023-01-01');
});
PSR-4 Autoloading Issues:
composer dump-autoload is run and vendor/autoload.php is loaded.Deprecation Not Found:
@expectedDeprecation to PHPUnit 9+:
/**
* @expectedDeprecation Deprecated message
*/
public function testDeprecation()
{
SomeClass::deprecatedMethod();
}
ClockMock Not Working:
setClock() is called before creating DateTime instances.ClockMock::getTime() to verify the current time:
$this->assertEquals('2023-01-01', $this->getClock()->getTime()->format('Y-m-d'));
CI/CD Failures:
phpunit.xml:
<php>
<ini name="display_errors" value="1"/>
<ini name="display_startup_errors" value="1"/>
</php>
Custom Deprecation Traits:
Extend ExpectUserDeprecationMessageTrait for project-specific assertions:
trait CustomDeprecationTrait
{
protected function expectCustomDeprecation($message)
{
$this->expectUserDeprecationMessage($message);
// Add custom logic (e.g., log deprecations)
}
}
Global Clock Setup:
Create a base test case to auto-configure ClockMock:
abstract class BaseTestCase extends TestCase
{
protected function setUp(): void
{
$this->setClock(new ClockMock('2023-01-01'));
}
}
Deprecation Reporting: Integrate with Laravel’s logging to track deprecations:
$this->expectUserDeprecationMessage('message', function ($e) {
Log::warning('Deprecation triggered: ' . $e->getMessage());
});
PHPUnit Listeners:
Use the bridge’s DeprecationExtension to customize de
How can I help you explore Laravel packages today?