CodePark/ questions / External services & queues
START PRACTICINGPRACTICE
Backend question · Backend testing › External services & queues

Most message brokers deliver at least once. How do you test that a consumer is idempotent?

Write tests that deliver the same message more than once. Then check that the effect happened only once.

The basic test: call the handler twice with the same payload and the same message id. Then check there is:

  • one order row
  • one charge on the stubbed payment gateway
  • one email

The harder cases:

  • The handler crashes after writing to the database but before it acks (confirms the message). The broker then delivers the message again.
  • Two workers process the same message at the same time. Use Promise.all against a real database, so the unique constraint or lock is really tested.
  • Messages arrive in the wrong order.

The code usually uses a "processed messages" table with a unique key, or a natural unique constraint. It writes this in the same transaction as the business change. The tests must prove this design holds. That is why they need the real database, not a mocked repository.

  • Deliver the same message twice and check there is only one effect.
  • Simulate a crash before the ack, then a second delivery.
  • Test two workers processing the same message at once, against a real database.
  • Use an idempotency key or unique constraint in the same transaction as the business change.