Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpunit Bridge Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. 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).

  2. 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
        }
    }
    
  3. Where to Look First:


Implementation Patterns

Core Workflows

1. Testing Deprecation Warnings

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();
    }
}

2. Mocking Time-Sensitive Logic

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());
    }
}

3. Integrating with Laravel’s TestCase

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;
}

4. Handling PHPUnit Attributes (v10+)

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>

5. CI/CD Enforcement

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"

Integration Tips

Laravel-Specific Patterns

  1. 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());
        }
    }
    
  2. 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();
        }
    }
    
  3. 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);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. TestCase Patching Conflicts:

    • The bridge automatically patches TestCase classes. If you extend Laravel’s TestCase or a custom base class, ensure the bridge’s traits are compatible.
    • Fix: Explicitly include the bridge’s traits in your custom test case:
      use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
      
      class CustomTestCase extends \Tests\TestCase
      {
          use ExpectUserDeprecationMessageTrait;
      }
      
  2. PHPUnit Version Mismatches:

    • The bridge supports PHPUnit 9+, but behavior differs between versions (e.g., attribute parsing in PHPUnit 10).
    • Fix: Pin PHPUnit to a compatible version in composer.json:
      "require-dev": {
          "phpunit/phpunit": "^10.0"
      }
      
  3. Deprecation Message Mismatches:

    • Asserting exact deprecation messages can fail due to whitespace or formatting differences.
    • Fix: Use partial matches or regex:
      $this->expectUserDeprecationMessage(
          Deprecation::class,
          '/Deprecated message.*/'
      );
      
  4. ClockMock and Time Zones:

    • ClockMock may not respect Laravel’s default time zone settings.
    • Fix: Set the time zone explicitly:
      $this->freezeTime('2023-01-01 12:00:00', 'UTC');
      
  5. PSR-4 Path Resolution Issues:

    • The bridge may fail to resolve paths in custom test environments.
    • Fix: Ensure vendor/autoload.php is loaded and PSR-4 autoloading is configured in composer.json.
  6. Interactive Composer Questions:

    • Older versions of the bridge may trigger Composer interactive prompts during tests.
    • Fix: Update to a recent version (v7.3.1+) or suppress prompts:
      COMPOSER_NO_INTERACTION=1 php artisan test
      
  7. PhptTestCase Limitations:

    • The bridge may not fully support PHPUnit’s PhptTestCase (e.g., for .phpt files).
    • Fix: Avoid using PhptTestCase or manually handle deprecations in these tests.

Debugging Tips

  1. Enable Verbose Output: Run tests with -v to debug bridge initialization:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai