PHP code example of zenstruck / messenger-test

1. Go to this page and download the library: Download zenstruck/messenger-test library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

zenstruck / messenger-test example snippets


    Zenstruck\Messenger\Test\ZenstruckMessengerTestBundle::class => ['test' => true],
    

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // ...some code that routes messages to your configured transport

        // assert against the queue
        $this->transport()->queue()->assertEmpty();
        $this->transport()->queue()->assertNotEmpty();
        $this->transport()->queue()->assertCount(3);
        $this->transport()->queue()->assertContains(MyMessage::class); // queue contains this message
        $this->transport()->queue()->assertContains(MyMessage::class, 3); // queue contains this message 3 times
        $this->transport()->queue()->assertContains(MyMessage::class, 0); // queue contains this message 0 times
        $this->transport()->queue()->assertNotContains(MyMessage::class); // queue not contains this message

        // access the queue data
        $this->transport()->queue(); // Envelope[]
        $this->transport()->queue()->messages(); // object[] the messages unwrapped from envelope
        $this->transport()->queue()->messages(MyMessage::class); // MyMessage[] just messages matching class
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // ...some code that routes messages to your configured transport

        // let's assume 3 messages are on this queue
        $this->transport()->queue()->assertCount(3);

        $this->transport()->process(1); // process one message
        $this->transport()->processOrFail(1); // equivalent to above but fails if queue empty

        $this->transport()->queue()->assertCount(2); // queue now only has 2 items

        $this->transport()->process(); // process all messages on the queue
        $this->transport()->processOrFail(); // equivalent to above but fails if queue empty

        $this->transport()->queue()->assertEmpty(); // queue is now empty
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Stamp\DelayStamp;
use Zenstruck\Messenger\Test\InteractsWithMessenger;
use Zenstruck\Messenger\Test\Transport\TestTransport;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // manually send a message to your transport
        $this->transport()->send(new MyMessage());

        // send with stamps
        $this->transport()->send(Envelope::wrap(new MyMessage(), [new SomeStamp()]));

        // send "pre-encoded" message
        $this->transport()->send(['body' => '...']);

        $queue = $this->transport()->queue();
        $dispatched = $this->transport()->dispatched();
        $acknowledged = $this->transport()->acknowledged(); // messages successfully processed
        $rejected = $this->transport()->rejected(); // messages not successfully processed

        // The 4 above variables are all instances of Zenstruck\Messenger\Test\EnvelopeCollection
        // which is a countable iterator with the following api (using $queue for the example).
        // Methods that return Envelope(s) actually return TestEnvelope(s) which is an Envelope
        // decorator (all standard Envelope methods can be used) with some stamp-related assertions.

        // collection assertions
        $queue->assertEmpty();
        $queue->assertNotEmpty();
        $queue->assertCount(3);
        $queue->assertContains(MyMessage::class); // contains this message
        $queue->assertContains(MyMessage::class, 3); // contains this message 3 times
        $queue->assertNotContains(MyMessage::class); // not contains this message

        // helpers
        $queue->count(); // number of envelopes
        $queue->all(); // TestEnvelope[]
        $queue->messages(); // object[] the messages unwrapped from their envelope
        $queue->messages(MyMessage::class); // MyMessage[] just instances of the passed message class

        // get specific envelope
        $queue->first(); // TestEnvelope - first one on the collection
        $queue->first(MyMessage::class); // TestEnvelope - first where message class is MyMessage
        $queue->first(function(Envelope $e): bool {
            return $e->getMessage() instanceof MyMessage && $e->getMessage()->isSomething();
        }); // TestEnvelope - first that matches the filter callback

        // Equivalent to above - use the message class as the filter function typehint to
        // auto-filter to this message type.
        $queue->first(fn(MyMessage $m): bool => $m->isSomething()); // TestEnvelope

        // TestEnvelope stamp assertions
        $queue->first()->assertHasStamp(DelayStamp::class);
        $queue->first()->assertNotHasStamp(DelayStamp::class);

        // reset collected messages on the transport
        $this->transport()->reset();

        // reset collected messages for all transports
        TestTransport::resetAll();

        // fluid assertions on different EnvelopeCollections
        $this->transport()
            ->queue()
                ->assertNotEmpty()
                ->assertContains(MyMessage::class)
            ->back() // returns to the TestTransport
            ->dispatched()
                ->assertEmpty()
            ->back()
            ->acknowledged()
                ->assertEmpty()
            ->back()
            ->rejected()
                ->assertEmpty()
            ->back()
        ;
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // ...some code that routes messages to your configured transport

        // disable exception catching
        $this->transport()->throwExceptions();

        // if processing fails, the exception will be thrown
        $this->transport()->process(1);

        // re-enable exception catching
        $this->transport()->catchExceptions();
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // disable intercept
        $this->transport()->unblock();

        // ...some code that routes messages to your configured transport
        // ...these messages are handled immediately

        // enable intercept
        $this->transport()->intercept();

        // ...some code that routes messages to your configured transport

        // if messages are on the queue when calling unblock(), they are processed
        $this->transport()->unblock();
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase // or WebTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        $this->transport('high')->queue();
        $this->transport('low')->dispatched();
    }
}


// Let's say somewhere in your app, you register some actions that should occur in the future:

$bus->dispatch(new Enevelope(new TakeSomeAction1(), [DelayStamp::delayFor(new \DateInterval('P1D'))])); // will be handled in 1 day
$bus->dispatch(new Enevelope(new TakeSomeAction2(), [DelayStamp::delayFor(new \DateInterval('P3D'))])); // will be handled in 3 days

// In your test, you can check that the action is not yet performed:

class TestDelayedActions extends KernelTestCase
{
    use InteractsWithMessenger;
    use ClockSensitiveTrait;

    public function testDelayedActions(): void
    {
        // 1. mock the clock, in order to perform sleeps
        $clock = self::mockTime();

        // 2. trigger the action that will dispatch the two messages

        // ...

        // 3. assert nothing happens yet
        $transport = $this->transport('async');

        $transport->process();
        $transport->queue()->assertCount(2);
        $transport->acknowledged()->assertCount(0);

        // 4. sleep, process queue, and assert some messages have been handled
        $clock->sleep(60 * 60 * 24); // wait one day
        $transport->process()->acknowledged()->assertContains(TakeSomeAction1::class);
        $this->asssertTakeSomeAction1IsHandled();

        // TakeSomeAction2 is still in the queue
        $transport->queue()->assertCount(1);

        $clock->sleep(60 * 60 * 24 * 2); // wait two other days
        $transport->process()->acknowledged()->assertContains(TakeSomeAction2::class);
        $this->asssertTakeSomeAction2IsHandled();
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // ... some code that uses the bus

        // Let's assume two messages are processed
        $this->bus()->dispatched()->assertCount(2);

        $this->bus()->dispatched()->assertContains(MessageA::class, 1);
        $this->bus()->dispatched()->assertContains(MessageB::class, 1);
    }
}

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Messenger\Test\InteractsWithMessenger;

class MyTest extends KernelTestCase
{
    use InteractsWithMessenger;

    public function test_something(): void
    {
        // ... some code that use bus

        // Let's assume two messages are handled by two different buses
        $this->bus('bus-a')->dispatched()->assertCount(1);
        $this->bus('bus-b')->dispatched()->assertCount(1);
        $this->bus('bus-c')->dispatched()->assertCount(0);

        $this->bus('bus-a')->dispatched()->assertContains(MessageA::class, 1);
        $this->bus('bus-b')->dispatched()->assertContains(MessageB::class, 1);
    }
}