Description
Hey,
First and foremost, congrats on shipping this, the content is very great 💪🏻
I wanted to discuss not sure issue are the best place but there is no alternative.
I mostly agree with everything but Use a fake MQ for the majority of testing
.
In my experience this is something you do because at the beginning of a project it reduces the cost of CI and helps tracking messages, however it does not translate to real use case. Like the advice to not query DB and always use REST API, I believe MQ should be treated the same way. In production you send something to a black box and maybe get it sometimes, it's important to test this too.
My main point, is that mocking a MQ is simple at first but then you need Fanout, TTL, dead-lettering, ack/nack and your mock is now a mess because you just rewrote your MQ.
Purging a queue is slow and not deterministic. When the purge/delete command arrives, some messages are in transit and the queue will not delete those until it get acknowledgment.
This main argument is understandable but easily defeated by using a prefixed queue name per test with a TTL. No need to purge, no need to wait for delete, tests can be run in parallel, etc...
but at the same time will kill the performance
I don't agree with this, a typical MQ software can hold thousand of queues with a very minimal amount of CPU/RAM.
If your MQ is a bottleneck there is something wrong (unless you are sending millions of jobs per second).
For example, rabbitmq with default configuration will hold the load of a normal CI without any issue and deliver messages in a few ms guaranteed. Even in production with high load you should expect < 10ms for delivery.
Given all of this background, a recommended MQ testing strategy is to use simplistic-fake for the majority of the tests, mostly the tests that cover the app flows
I would say, MQ should only be needed on E2E otherwise that means the code is not well decoupled. That's why it's not a problem to not mock it.
I would also add that in memory mock can be dangerous with language like JS that hold pointer ref. If your tests are running in parallel in the same process, you might end up sharing pointer ref or ending up with the same issue about queue name.
Anyway, it's not a dramatic thing, just as a person who did this mistake multiple times I felt like sharing my POV on this topic.