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

Messenger Test Laravel Package

zenstruck/messenger-test

Test helpers and assertions for symfony/messenger. Provides a TestTransport that intercepts and round-trips messages, lets you inspect queued items, assert counts/contents and processing states (acked/rejected), and optionally process queued messages in Kernel/Web tests.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require --dev zenstruck/messenger-test
    

    Add to composer.json under require-dev if not using auto-discovery.

  2. First Use Case Test a message handler with assertions:

    use Zenstruck\MessengerTest\Assertion\AssertsMessages;
    use Zenstruck\MessengerTest\Assertion\AssertsMessagesTrait;
    
    class SendEmailHandlerTest extends TestCase
    {
        use AssertsMessagesTrait;
    
        public function testHandlesSendEmailMessage()
        {
            $this->assertMessages([new SendEmailMessage('test@example.com')]);
    
            // Dispatch a message
            $this->dispatch(new SendEmailMessage('test@example.com'));
    
            // Assert it was dispatched
            $this->assertMessages([new SendEmailMessage('test@example.com')]);
        }
    }
    
  3. Key Classes to Explore

    • AssertsMessagesTrait: Core assertions for message handling.
    • AssertsMessages: Standalone assertion class.
    • MessageBus: Helper for testing message buses.
    • New: Retry configuration utilities (RetryTestTrait).

Implementation Patterns

Workflow: Testing Message Consumption

  1. Setup Use AssertsMessagesTrait in your test class:

    use Zenstruck\MessengerTest\Assertion\AssertsMessagesTrait;
    
    class MyTest extends TestCase
    {
        use AssertsMessagesTrait;
    }
    
  2. Assert Message Dispatch

    $this->assertMessages([new MyMessage('value')]);
    
  3. Dispatch Messages

    $this->dispatch(new MyMessage('value'));
    
  4. Assert Message Handling

    $this->assertMessagesHandled([new MyMessage('value')]);
    

Workflow: Testing Retry Behavior (New)

  1. Enable/Disable Retries Manually Use RetryTestTrait to control retry behavior:
    use Zenstruck\MessengerTest\Retry\RetryTestTrait;
    
    class RetryTest extends TestCase
    {
        use RetryTestTrait;
    
        public function testRetryBehavior()
        {
            // Disable retries globally
            $this->disableRetries();
    
            // Or enable retries with custom max attempts
            $this->enableRetries(3);
    
            $this->dispatch(new RetryableMessage());
            $this->assertMessages([new RetryableMessage()]);
        }
    }
    

Workflow: Testing Async Workers

  1. Mock the Transport

    $this->mockTransport();
    
  2. Dispatch and Assert

    $this->dispatch(new AsyncMessage());
    $this->assertMessages([new AsyncMessage()]);
    

Integration with Laravel

  • Service Provider Extend Zenstruck\MessengerTest\MessengerTestServiceProvider if customizing behavior:

    $this->app->register(MessengerTestServiceProvider::class);
    
  • Custom Assertions Extend AssertsMessages for project-specific assertions:

    class CustomAssertions extends AssertsMessages
    {
        public function assertMessageProcessed(MyMessage $message)
        {
            // Custom logic
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Transport Mocking

    • Forgetting to call $this->mockTransport() before dispatching messages will result in actual messages being sent to the queue.
    • Fix: Always mock the transport in tests:
      protected function setUp(): void
      {
          parent::setUp();
          $this->mockTransport();
      }
      
  2. Message Matching

    • Assertions use strict comparison by default. For complex objects, override equals() in your message class:
      public function equals($other): bool
      {
          return $this->id === $other->id;
      }
      
  3. Async Workers

    • Assertions for async workers require the message to be processed. Use $this->assertMessagesHandled() instead of $this->assertMessages():
      $this->assertMessagesHandled([new AsyncMessage()]);
      
  4. Retry Behavior (New)

    • Retries are now enabled by default in tests. If you need deterministic behavior, explicitly disable them:
      $this->disableRetries();
      
    • Fix: Use $this->enableRetries() or $this->disableRetries() at the start of your test methods to control retry logic.

Debugging

  • Inspect Queued Messages Use $this->getMessages() to debug:

    $messages = $this->getMessages();
    dd($messages);
    
  • Clear Queued Messages Use $this->clearMessages() to reset state between tests:

    $this->clearMessages();
    
  • Retry Debugging Use $this->getRetryCount() to inspect how many times a message was retried:

    $this->dispatch(new RetryableMessage());
    $this->assertRetryCount(2); // Assert message was retried twice
    

Configuration Quirks

  • Custom Message Bus If using a custom bus, bind it to the container:

    $this->app->bind('messenger.bus', function () {
        return new CustomBus([/* ... */]);
    });
    
  • Transport Configuration Ensure your config/messenger.php is properly set up for testing:

    'transports' => [
        'sync' => [
            'dsn' => 'sync://',
        ],
    ],
    
  • Retry Configuration Retry behavior can now be controlled per test or globally via service provider:

    // In a service provider
    $this->app->make('events')->listen('messenger.test.start', function () {
        $this->disableRetries(); // Disable retries for all tests
    });
    

Extension Points

  1. Custom Matchers Extend Zenstruck\MessengerTest\Matcher\MessageMatcher for custom matching logic.

  2. Event Listeners Add listeners to messenger.test events for pre/post-test hooks:

    $this->app->make('events')->listen('messenger.test.start', function () {
        // Pre-test logic
    });
    
  3. Assertion Macros Add custom assertions via macros:

    $this->assertMessages()->macro('assertProcessed', function (MyMessage $message) {
        // Custom assertion logic
    });
    
  4. Retry Extensions (New) Extend retry behavior by implementing custom retry logic:

    $this->app->bind('messenger.test.retry', function () {
        return new CustomRetryHandler();
    });
    
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