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

Test Utilities Laravel Package

eventsauce/test-utilities

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require --dev eventsauce/test-utilities
    

    Ensure eventsauce/eventsauce (v2.0 or v3.0) and PHPUnit (v8.5+) are installed.

  2. First Use Case: Testing Event Sourcing Use the EventSauce\TestUtilities\TestUtil trait in your PHPUnit test class to simplify event sourcing assertions:

    use EventSauce\TestUtilities\TestUtil;
    
    class MyAggregateTest extends TestCase
    {
        use TestUtil;
    
        public function testAggregateBehavior()
        {
            $aggregate = new MyAggregate();
            $this->assertEvents($aggregate, [new MyEvent()]);
        }
    }
    
  3. Key Entry Points

    • assertEvents(): Verify emitted events.
    • assertEvent(): Check for a single event.
    • assertNoEvents(): Ensure no events were emitted.
    • assertEventOrder(): Validate event sequence.

    Refer to EventSauce Testing Docs for full API.


Implementation Patterns

Workflow: Testing Aggregate Roots

  1. Setup Use TestUtil to mock event storage and simplify assertions:

    use EventSauce\TestUtilities\TestUtil;
    
    class OrderAggregateTest extends TestCase
    {
        use TestUtil;
    
        public function testOrderCreation()
        {
            $order = new OrderAggregate();
            $order->create('user-123', 100.00);
    
            $this->assertEvents($order, [
                new OrderCreated('user-123', 100.00),
                new OrderInitialized()
            ]);
        }
    }
    
  2. Integration with EventSauce

    • Pair with EventSauce\EventSourcing\EventSourcingRepository for real storage tests.
    • Use TestUtil::assertEvent() to validate event properties:
      $this->assertEvent($order, OrderCreated::class, function ($event) {
          $this->assertEquals(100.00, $event->amount());
      });
      
  3. Testing Projections

    • Combine with EventSauce\Projection\Projection to test read models:
      $projection = new OrderProjection();
      $this->runProjection($projection, [
          new OrderCreated('user-123', 100.00)
      ]);
      $this->assertEquals(100.00, $projection->getTotal());
      
  4. Mocking External Services

    • Use TestUtil::mock() to stub dependencies (e.g., payment gateways) during event tests:
      $this->mock(PaymentGateway::class, function ($mock) {
          $mock->shouldReceive('charge')->once();
      });
      

Gotchas and Tips

Pitfalls

  1. Event Matching Strictness

    • assertEvents() uses strict type checking by default. Use true as the 3rd argument to relax matching:
      $this->assertEvents($aggregate, [new MyEvent()], true); // Loose matching
      
    • Tip: Prefer strict matching (false) to catch typos in event classes.
  2. Event Order Sensitivity

    • assertEventOrder() is order-sensitive. Reorder events in the test if the actual sequence differs from expectations.
  3. PHPUnit Version Conflicts

    • Ensure PHPUnit version aligns with composer.json constraints (e.g., ^9.4). Use:
      composer require --dev phpunit/phpunit:^9.5
      
  4. Aggregate Hydration Issues

    • If testing event-sourced aggregates, ensure TestUtil is used after hydration:
      // ❌ Wrong: TestUtil won't track events emitted during hydration.
      $aggregate = $repository->hydrate($id);
      
      // ✅ Correct: Use TestUtil for new interactions.
      $this->assertEvents($aggregate, []);
      $aggregate->doSomething();
      

Debugging Tips

  1. Event Dumping Use TestUtil::getRecordedEvents() to inspect emitted events:

    var_dump($this->getRecordedEvents($aggregate));
    
  2. Projection Debugging For failing projections, log intermediate state:

    $this->runProjection($projection, $events, function ($projection) {
        error_log('Projection state: ' . print_r($projection->getState(), true));
    });
    
  3. Custom Assertions Extend TestUtil for domain-specific checks:

    protected function assertCustomEvent($aggregate, $expected)
    {
        $this->assertEvent($aggregate, CustomEvent::class, function ($event) use ($expected) {
            $this->assertEquals($expected->value(), $event->value());
        });
    }
    

Extension Points

  1. Custom Event Matchers Override TestUtil::matches() to support custom event logic:

    protected function matches($event, $expected, $strict = false)
    {
        if ($expected instanceof CustomEvent) {
            return $event->id() === $expected->id();
        }
        return parent::matches($event, $expected, $strict);
    }
    
  2. Integration with Laravel

    • Use TestUtil in Laravel’s TestCase:
      use EventSauce\TestUtilities\TestUtil;
      use Orchestra\Testbench\TestCase as LaravelTestCase;
      
      class AggregateTest extends LaravelTestCase
      {
          use TestUtil;
          // ...
      }
      
    • Tip: Bind EventSourcingRepository in TestCase::setUp() for Laravel-specific storage.
  3. Performance Testing

    • Simulate high-throughput event streams:
      $this->assertEvents($aggregate, array_fill(0, 1000, new BulkEvent()));
      
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky
spatie/mailcoach-vapor