symfony/phpunit-bridge
Symfony PHPUnit Bridge adds PHPUnit utilities with a focus on managing and asserting deprecations. It improves test output, helps catch legacy API usage, and eases upgrades by tracking deprecation notices during your test suite runs.
Installation: Add the package to your Laravel project via Composer:
composer require symfony/phpunit-bridge
Ensure your phpunit.xml includes the bridge’s autoloader (handled automatically if using Laravel’s default phpunit.xml).
First Use Case:
Test a deprecation warning in a Symfony component used by Laravel. For example, if your code uses a deprecated Symfony HttpClient method:
use Symfony\Component\HttpClient\Exception\Deprecation;
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class MyTest extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
public function testDeprecationWarning()
{
$this->expectUserDeprecationMessage(
Deprecation::class,
'The "method()" is deprecated since Symfony 6.0.'
);
// Trigger the deprecated code
$client->method(); // Assume this calls a deprecated method
}
}
Where to Look First:
phpunit.xml to ensure the bridge is loaded (check for <bootstrap> or autoloader configurations).ExpectUserDeprecationMessageTrait for deprecation testing.Use ExpectUserDeprecationMessageTrait to assert deprecation warnings in tests:
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class DeprecationTest extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
public function testDeprecatedMethod()
{
$this->expectUserDeprecationMessage(
Deprecation::class,
'Deprecated message here.'
);
// Code under test that triggers the deprecation
$this->triggerDeprecatedCode();
}
}
Leverage ClockMock to simulate dates in tests (e.g., for scheduled tasks or time-based logic):
use Symfony\Bridge\PhpUnit\ClockMock;
class TimeTest extends \Tests\TestCase
{
use ClockMock;
protected function setUp(): void
{
$this->freezeTime('2023-01-01 12:00:00');
}
public function testScheduledTask()
{
$this->assertEquals('2023-01-01 12:00:00', now()->toDateTimeString());
}
}
Extend Laravel’s TestCase and use the bridge’s traits:
use Illuminate\Foundation\Testing\TestCase as LaravelTestCase;
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class CustomTestCase extends LaravelTestCase
{
use ExpectUserDeprecationMessageTrait;
}
Configure the bridge to work with PHPUnit 10’s attributes (e.g., @group):
<!-- phpunit.xml -->
<phpunit bootstrap="vendor/autoload.php">
<extensions>
<extension class="Symfony\Bridge\PhpUnit\PhpUnitBridgeExtension"/>
</extensions>
</phpunit>
Fail builds on deprecation warnings by ensuring tests include assertions for deprecated code. Example .github/workflows/tests.yml:
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: php artisan test --testdox-html --log-junit tests/_output/results.xml
Add a step to validate no deprecation warnings are ignored:
php artisan test --filter="DeprecationTest"
Service Container Mocking:
Combine ClockMock with Laravel’s service container to test time-sensitive services:
use Symfony\Bridge\PhpUnit\ClockMock;
class ScheduledJobTest extends \Tests\TestCase
{
use ClockMock;
protected function setUp(): void
{
$this->freezeTime('2023-01-01 00:00:00');
$this->app->bind(\Carbon\Carbon::class, fn() => \Carbon\Carbon::createFromDate(2023, 1, 1));
}
public function testJobExecution()
{
$this->assertEquals(0, ScheduledJob::run()->count());
}
}
Deprecation Testing in Packages: If your Laravel package uses Symfony components, test deprecations in isolation:
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class HttpClientTest extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
public function testDeprecatedClient()
{
$this->expectUserDeprecationMessage(
Deprecation::class,
'Deprecated client method.'
);
$client = new HttpClient();
$client->deprecatedMethod();
}
}
Data Providers for Deprecation Tests: Use PHPUnit’s data providers to test multiple deprecation scenarios:
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class DeprecationDataTest extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
public function deprecationScenarios()
{
return [
['method1', 'Deprecated message 1.'],
['method2', 'Deprecated message 2.'],
];
}
/**
* @dataProvider deprecationScenarios
*/
public function testMultipleDeprecations($method, $message)
{
$this->expectUserDeprecationMessage(
Deprecation::class,
$message
);
$this->triggerDeprecatedMethod($method);
}
}
TestCase Patching Conflicts:
TestCase classes. If you extend Laravel’s TestCase or a custom base class, ensure the bridge’s traits are compatible.use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
class CustomTestCase extends \Tests\TestCase
{
use ExpectUserDeprecationMessageTrait;
}
PHPUnit Version Mismatches:
composer.json:
"require-dev": {
"phpunit/phpunit": "^10.0"
}
Deprecation Message Mismatches:
$this->expectUserDeprecationMessage(
Deprecation::class,
'/Deprecated message.*/'
);
ClockMock and Time Zones:
ClockMock may not respect Laravel’s default time zone settings.$this->freezeTime('2023-01-01 12:00:00', 'UTC');
PSR-4 Path Resolution Issues:
vendor/autoload.php is loaded and PSR-4 autoloading is configured in composer.json.Interactive Composer Questions:
COMPOSER_NO_INTERACTION=1 php artisan test
PhptTestCase Limitations:
PhptTestCase (e.g., for .phpt files).PhptTestCase or manually handle deprecations in these tests.-v to debug bridge initialization:
How can I help you explore Laravel packages today?