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

Plugin Phpunit Laravel Package

psalm/plugin-phpunit

Psalm plugin that teaches Psalm about PHPUnit tests. Adds better type inference and assertions for PHPUnit APIs so your test suite is analyzed more accurately. Requires Psalm v4+. Install via Composer and enable with psalm-plugin.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the plugin in your Laravel project:
    composer require --dev psalm/plugin-phpunit
    
  2. Enable the plugin for Psalm:
    vendor/bin/psalm-plugin enable psalm/plugin-phpunit
    
  3. Configure Psalm to analyze test files: Update psalm.xml to include your test directory:
    <file-list>
        <dir>tests/</dir>
    </file-list>
    
  4. Run Psalm with the plugin:
    ./vendor/bin/psalm --init
    

First Use Case: Analyzing a Test Class

Run Psalm on your test files to immediately see improvements:

./vendor/bin/psalm --no-cache

Example Output: Psalm will now understand PHPUnit assertions (e.g., assertSame(), assertInstanceOf()) and validate their types, reducing false positives in your tests.


Implementation Patterns

Core Workflows

  1. Type Validation for Assertions Psalm will analyze assertion methods (e.g., assertEquals(), assertInstanceOf()) and validate their arguments. For example:

    public function testUserIdIsInteger(): void
    {
        $user = User::factory()->create();
        $this->assertSame(1, $user->id); // Psalm checks if `$user->id` is an int
    }
    
    • Pattern: Use assertSame()/assertEquals() with typed arguments to leverage Psalm’s type inference.
  2. Data Provider Analysis Psalm validates @dataProvider methods and their return types:

    #[DataProvider('integerProvider')]
    public function testIntegerHandling(int $value): void
    {
        $this->assertIsInt($value);
    }
    
    public function integerProvider(): iterable
    {
        yield [1];
        yield [2];
    }
    
    • Pattern: Ensure data providers return iterable or array types. Psalm will flag mismatches (e.g., returning a scalar).
  3. Attribute Support Psalm understands PHPUnit 9+ attributes (#[Test], #[DataProvider], #[Before]):

    #[Test]
    public function testAttributeSupport(): void
    {
        $this->assertTrue(true);
    }
    
    • Pattern: Migrate from annotations (@test) to attributes for full Psalm support.
  4. Mocking and Stubs Psalm validates mock interactions (e.g., createMock(), getMockBuilder()):

    $mock = $this->createMock(UserRepository::class);
    $mock->method('find')->willReturn(new User());
    
    • Pattern: Use createMock() with generic types (e.g., createMock(UserRepository::class)) for better type hints.

Integration Tips

  • Laravel-Specific Use Cases:

    • Eloquent Tests: Validate queries return expected types (e.g., Collection vs. Builder):
      $users = User::query()->where('active', true)->get();
      $this->assertInstanceOf(Collection::class, $users);
      
    • API Tests: Ensure JSON responses match asserted types:
      $response = $this->get('/api/users');
      $this->assertJsonStructure([['id', 'name']]);
      
    • Service Container: Validate bindings in tests:
      $this->app->bind(UserRepository::class, fn () => new UserRepository());
      $this->assertTrue($this->app->has(UserRepository::class));
      
  • CI/CD Pipeline: Add Psalm to your test suite in phpunit.xml:

    <listeners>
        <listener class="Psalm\Plugin\PHPUnit\Listener" />
    </listeners>
    

    Run Psalm before PHPUnit to fail fast on type errors:

    ./vendor/bin/psalm --no-cache && ./vendor/bin/phpunit
    
  • Configuration: Customize Psalm’s behavior in psalm.xml:

    <plugin_class>Psalm\Plugin\PHPUnit\Plugin</plugin_class>
    <param name="checkForThrowsDocblock">true</param> <!-- Validate `@throws` annotations -->
    

Gotchas and Tips

Pitfalls

  1. False Positives with Dynamic Types: Psalm may flag assertions involving dynamic types (e.g., mixed or array) as errors. Use @psalm-suppress sparingly:

    #[psalm-suppress MixedArgument]
    $this->assertEquals($dynamicValue, 'expected');
    
  2. Data Provider Mismatches: If a data provider returns a tuple but the test expects separate arguments, Psalm will report an error. Ensure consistency:

    // Correct: Data provider returns iterable of arrays
    public function provider(): iterable
    {
        yield [1, 'one'];
        yield [2, 'two'];
    }
    
  3. Legacy PHPUnit Annotations: The plugin prioritizes attributes (#[Test]) over annotations (@test). Update old tests to avoid warnings.

  4. Mock Method Signatures: Psalm may not infer mock method return types if they’re not explicitly set. Use willReturn() with typed values:

    $mock->method('getName')->willReturn('John'); // Psalm infers `string`
    
  5. Performance Overhead: Analyzing large test suites may slow down Psalm. Use --no-cache in CI and cache results locally:

    ./vendor/bin/psalm --init && ./vendor/bin/psalm --no-cache
    

Debugging Tips

  • Enable Verbose Output: Run Psalm with -v to debug plugin behavior:
    ./vendor/bin/psalm -v
    
  • Isolate Test Files: Analyze a single test file to pinpoint issues:
    ./vendor/bin/psalm tests/Feature/UserTest.php
    
  • Check Plugin Compatibility: Ensure your Psalm version matches the plugin’s requirements (e.g., Psalm v7+ for recent releases). Update via:
    composer require psalm/psalm:^7.0 --dev
    

Extension Points

  1. Custom Assertions: Extend the plugin to support custom assertions by defining stubs in psalm.xml:

    <stub_files>
        <file>stubs/CustomAssertions.php</file>
    </stub_files>
    

    Example stub:

    namespace PHPUnit\Framework\Assert {
        function assertCustomType(mixed $actual, string $expectedType): void { /* ... */ }
    }
    
  2. Data Provider Enhancements: Add support for complex data providers (e.g., generators) by extending the plugin’s ProviderAnalyzer class.

  3. Laravel-Specific Stubs: Create stubs for Laravel’s testing helpers (e.g., createMock(), JsonResponse) to improve type inference:

    namespace Illuminate\Testing {
        class JsonResponse {
            public function assertJsonStructure(array $structure): void { /* ... */ }
        }
    }
    

Configuration Quirks

  • Excluding Files: Use <exclude-files> in psalm.xml to skip problematic test files:
    <exclude-files>
        <file>tests/Integration/SlowTests.php</file>
    </exclude-files>
    
  • Strict Mode: Enable strict_types=1 in test files to catch more type errors:
    <?php declare(strict_types=1);
    
  • Plugin Order: Ensure psalm/plugin-phpunit is loaded after core Psalm plugins in psalm.xml:
    <plugins>
        <plugin_class>Psalm\Plugin\PHPUnit\Plugin</plugin_class>
    </plugins>
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity