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

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

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

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

    • Symfony Documentation for core features.
    • vendor/symfony/phpunit-bridge/ for source code (e.g., ClockMock, ExpectUserDeprecationMessageTrait).
    • Laravel’s phpunit.xml to configure PHPUnit behavior (e.g., deprecation flags).

Implementation Patterns

Core Workflows

1. Deprecation Testing

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

2. Mocking Time with ClockMock

Replace 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'));
}

3. Laravel-Specific Integration

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

4. CI/CD Pipeline Integration

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>

5. Data Provider Testing

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

Laravel-Specific Tips

  • 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']);
    }
    

Gotchas and Tips

Pitfalls

  1. PHPUnit Version Conflicts:

    • The bridge works with PHPUnit 9+ (Laravel 9+) and PHPUnit 10+ (Laravel 10+).
    • Gotcha: If using PHPUnit 10+, ensure bootstrap: false in phpunit.xml to avoid conflicts:
      <phpunit bootstrap="false">
      
    • Fix: Update phpunit.xml or use symfony/phpunit-bridge:^7.4 for PHPUnit 10+.
  2. Deprecation Message Mismatches:

    • expectUserDeprecationMessage() is strict about message content.
    • Gotcha: Whitespace or punctuation differences cause failures.
    • Fix: Use regex or partial matches:
      $this->expectUserDeprecationMessage('/Deprecated: .*/');
      
  3. ClockMock Scope:

    • ClockMock only affects DateTime/DateTimeImmutable instances created after setup.
    • Gotcha: Pre-created instances (e.g., cached) won’t update.
    • Fix: Reset the clock or recreate instances:
      $this->setClock(new ClockMock('2023-01-02'));
      $newDateTime = new DateTime(); // Uses new clock time
      
  4. Laravel Service Provider Conflicts:

    • Gotcha: Overriding DateTimeInterface in the container may conflict with ClockMock.
    • Fix: Bind ClockMock explicitly in tests:
      $this->app->bind(\DateTimeInterface::class, function () {
          return new ClockMock('2023-01-01');
      });
      
  5. PSR-4 Autoloading Issues:

    • Gotcha: The bridge may fail to find test classes if autoloading is misconfigured.
    • Fix: Ensure composer dump-autoload is run and vendor/autoload.php is loaded.

Debugging Tips

  1. Deprecation Not Found:

    • Verify the deprecation is triggered in the test environment (not production).
    • Debug: Add @expectedDeprecation to PHPUnit 9+:
      /**
       * @expectedDeprecation Deprecated message
       */
      public function testDeprecation()
      {
          SomeClass::deprecatedMethod();
      }
      
  2. ClockMock Not Working:

    • Check if setClock() is called before creating DateTime instances.
    • Debug: Use ClockMock::getTime() to verify the current time:
      $this->assertEquals('2023-01-01', $this->getClock()->getTime()->format('Y-m-d'));
      
  3. CI/CD Failures:

    • Gotcha: Deprecation warnings may be suppressed in CI.
    • Fix: Add to phpunit.xml:
      <php>
          <ini name="display_errors" value="1"/>
          <ini name="display_startup_errors" value="1"/>
      </php>
      

Extension Points

  1. 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)
        }
    }
    
  2. 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'));
        }
    }
    
  3. Deprecation Reporting: Integrate with Laravel’s logging to track deprecations:

    $this->expectUserDeprecationMessage('message', function ($e) {
        Log::warning('Deprecation triggered: ' . $e->getMessage());
    });
    
  4. PHPUnit Listeners: Use the bridge’s DeprecationExtension to customize de

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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4