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 Consecutive Params Laravel Package

seec/phpunit-consecutive-params

Bring back PHPUnit’s removed withConsecutive behavior. This lightweight dev helper provides a drop-in replacement via a trait, letting you assert different parameter sets across consecutive mock calls using ->with(...$this->withConsecutive(...)).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev seec/phpunit-consecutive-params
    

    Add the trait to your test class:

    use SEEC\PhpUnit\Helper\ConsecutiveParams;
    
  2. First Use Case: Replace withConsecutive() calls in legacy tests or new mock expectations:

    $mock->expects($this->exactly(3))
        ->method('process')
        ->with(...$this->withConsecutive(
            ['input1', 'output1'],
            ['input2', 'output2']
        ));
    
  3. Where to Look First:

    • Check the README for syntax examples.
    • Review existing tests in your codebase for withConsecutive() usage (PHPUnit 9+ removed this natively).

Implementation Patterns

Core Workflow

  1. Mock Expectations: Use withConsecutive() for sequential method calls with varying parameters:

    $mock->method('handle')
        ->withConsecutive(
            [$this->equalTo('user1'), $this->anything()],
            [$this->equalTo('user2'), $this->isType('array')]
        );
    
  2. Integration with PHPUnit Constraints: Combine with PHPUnit matchers for dynamic assertions:

    $mock->expects($this->atLeastOnce())
        ->method('validate')
        ->with(...$this->withConsecutive(
            [$this->stringContains('test')],
            [$this->logicalNot($this->stringContains('fail'))]
        ));
    
  3. Data-Driven Tests: Generate test cases from arrays:

    $testCases = [
        ['input' => 'a', 'expected' => 'A'],
        ['input' => 'b', 'expected' => 'B'],
    ];
    $mock->method('transform')
        ->withConsecutive(...array_map(
            fn($case) => [$case['input']],
            $testCases
        ));
    
  4. Legacy Test Migration: Replace deprecated withConsecutive() in existing tests:

    // Before (PHPUnit <9)
    $mock->withConsecutive(...);
    
    // After (with trait)
    $mock->with(...$this->withConsecutive(...));
    

Laravel-Specific Patterns

  1. Service Container Mocking: Test dependency injection sequences:

    $container = $this->createMock(Container::class);
    $container->method('make')
        ->withConsecutive(
            ['App\Services\UserService'],
            ['App\Services\Logger']
        );
    
  2. Event Listeners: Verify event dispatch order:

    $dispatcher = $this->createMock(Dispatcher::class);
    $dispatcher->expects($this->once())
        ->method('dispatch')
        ->withConsecutive(
            [$this->isInstanceOf(UserRegistered::class)],
            [$this->isInstanceOf(UserLoggedIn::class)]
        );
    
  3. Queue Workers: Test job processing sequences:

    $queue = $this->createMock(Queue::class);
    $queue->method('push')
        ->withConsecutive(
            [$this->isInstanceOf(SendEmailJob::class)],
            [$this->isInstanceOf(ProcessPaymentJob::class)]
        );
    

Gotchas and Tips

Common Pitfalls

  1. Parameter Spread Operator:

    • Gotcha: Forgetting ... before withConsecutive() causes runtime errors.
    • Fix: Always use with(...$this->withConsecutive(...)).
  2. Strict Typing:

    • Gotcha: PHP 8+ strict types may fail if parameter arrays don’t match expected shapes.
    • Tip: Use returnType() or returnSelf() constraints for strict mocks:
      $mock->method('getData')
          ->willReturnOnConsecutiveCalls(
              $this->returnValue('string'),
              $this->returnValue(['array'])
          );
      
  3. Order Sensitivity:

    • Gotcha: withConsecutive() enforces strict call order. Reordering parameters breaks tests.
    • Tip: Use with() for order-agnostic assertions if sequence doesn’t matter.
  4. IDE Support:

    • Gotcha: Some IDEs (e.g., PHPStorm) may flag withConsecutive() as undefined.
    • Fix: Add @mixin annotation to test classes:
      /** @mixin \SEEC\PhpUnit\Helper\ConsecutiveParams */
      

Debugging Tips

  1. Assertion Failures:

    • Use var_dump() to inspect parameter arrays:
      var_dump($this->withConsecutive([...]));
      
    • Check PHPUnit’s diff output for mismatched parameters.
  2. Performance:

    • Tip: For large test suites, cache withConsecutive() results:
      private $consecutiveParams = null;
      protected function getConsecutiveParams(): array {
          return $this->consecutiveParams ??= [
              ['param1', 'param2'],
              // ...
          ];
      }
      
  3. Configuration Quirks:

    • Tip: Ensure phpunit.xml uses PHPUnit 9+:
      <phpunit bootstrap="vendor/autoload.php">
          <extensions>
              <extension class="SEEC\PhpUnit\Helper\ConsecutiveParams"/>
          </extensions>
      </phpunit>
      

Extension Points

  1. Custom Matchers: Extend the trait for domain-specific assertions:

    trait CustomConsecutiveParams extends ConsecutiveParams {
        protected function withConsecutiveEmails(array ...$emails): array {
            return array_map(
                fn($email) => [$this->isInstanceOf(Email::class)->and($this->equalTo($email))],
                $emails
            );
        }
    }
    
  2. Dynamic Generation: Generate parameters from database fixtures:

    $users = User::all();
    $mock->method('processUser')
        ->withConsecutive(...array_map(
            fn($user) => [$user->id],
            $users->toArray()
        ));
    
  3. Integration with Factories: Combine with Laravel Factories for realistic test data:

    $mock->method('handleOrder')
        ->withConsecutive(...OrderFactory::new()->count(3)->make()->map(
            fn($order) => [$order->id]
        ));
    
  4. Parallel Testing:

    • Tip: Avoid shared state in withConsecutive() for parallel test runs.
    • Use static properties cautiously:
      static private $sharedParams = [];
      
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.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony