zenstruck / messenger-test

Assertions and helpers for testing your symfony/messenger queues.
MIT License
218 stars 15 forks source link

Messenger on non routed messages #41

Closed flohw closed 1 year ago

flohw commented 2 years ago

Hello,

I just found this library which may feet our needs and usable with your browser and foundry library which we already like :slightly_smiling_face:

We are using the messenger with async message and also messages which are not routed. Is there a way to handle them with this library? As there is no transport, I have a doubt but we can't route all of our message and most of them must be kept synchronous.

Maybe you can give me an advice on how I can test my message is dispatched by my controller? I didn't find a solution except by using the profiler but it might not be the better solution, isn't it?

Thanks

kbond commented 2 years ago

By "non-routed message", I guess you mean the default sync handling?

Right now, you can only test by creating a sync test transport and routing these messages to it:

framework:
    messenger:
        transports:
            sync: 'test://?intercept=false'
        routing:
            'App\Message\MyMessage': sync

What are you trying to achieve by using this library for these messages? Since these messages are dispatched immediately, can't you test the effect of the dispatch?

flohw commented 2 years ago

Indeed I meant the default sync handling, messages which are not listed in framework.messenger.routing configuration.

I can test the effect but sometimes they are a bit hard and the better alternative would be some unit tests on the handler. If the only way is to define a sync transport and list all of my messages I will try to test the effect (mainly check if entity is in the db or not)

Thanks

kbond commented 2 years ago

I think a common pattern is to make Sync and Async interfaces and all your messages implement one or the other. In your routing, send Sync messages to the sync transport and Async messages to the async transport. If you did this, you could use this library the way you want.

flohw commented 2 years ago

Which I didn't and regret know ^^ And we have too many messages now to be able to change it easily. Plus the team has grown up. Maybe on the next big update :slightly_smiling_face:

Thank you for your advice and patience :stuck_out_tongue:

kbond commented 2 years ago

To clarify, are you wanting to just see what sync messages were dispatched in your tests? Or do you want to intercept them?

flohw commented 2 years ago

I only want to know if the message I dispatched in my controller is the one I expect yes. Nothing more.

kbond commented 2 years ago

Got it. One solution I'm thinking of is for this library to provide a MessageBus decorator for each defined bus (very similar to TraceableMessageBus that the profiler uses). You could use this to inspect the dispatched messages in your tests. I'm just not sure how something like this would fit int the current API without being confusing.

flohw commented 2 years ago

Yes, that's what I was thinking of too: defining a custom message bus in services_test.yaml to be able to trace this messages and being able to retrieve it from the test self::getContainer()->get(TestMessageBus::class)->getMessages().

This is what a colleagues is doing in his tests. Something like that.

But if there is a solution to prevent the manual definition of such service, it would be great :grinning:

kbond commented 2 years ago

Jotting down some ideas:

class SomeTest extends KernelTestCase
{
    use InteractsWithMessenger;

    public function testSomething(): void
    {
        // do something that dispatches messages...

        $this->messenger()->... // deprecate current method (use transport() instead)
        $this->transport()->... // new method for existing functionality

        // new api
        $this->bus()->dispatched(); // EnvelopeCollection

        // if multiple buses configured, one must be chosen
        $this->bus('query.bus')->dispatched(); // EnvelopeCollection
    }
}
flohw commented 2 years ago

Yes, using the bus could open more possibilities I think than using the messenger.

Transport should indeed not be lost. I have no idea of use case as I am not using the messenger with this need of low level but I have the feeling it would be still needed. :-)

I think it makes more sense too (to query the bus instead of messenger as the method name suggests) as the configuration on symfony defines two things : transport and buses. :tada:

Thank you for this exchanges, very valuable and rewarding :-)

kbond commented 1 year ago

I believe this was solved with #54.

flohw commented 1 year ago

Yes. I thought it would have been closed automatically.

Thank you.