Helpers for testing code that publishes to an outbox.
Start Outboxer with testing: :manual in your test environment. No workers
run, so nothing is relayed behind your back and the Ecto SQL sandbox needs no
special arrangement: Outboxer.publish/2 writes through the test's own
connection and the rows roll back with the test.
# config/test.exs
config :my_app, :outboxer, testing: :manual
# application.ex
{Outboxer, [repo: MyApp.Repo, outboxes: [...]] ++ Application.get_env(:my_app, :outboxer, [])}Then, in a test:
import Outboxer.Testing
test "placing an order publishes an event" do
{:ok, order} = Orders.place(params)
envelope = assert_published(:orders, MyApp.Events.OrderPlaced)
assert JSON.decode!(envelope.payload)["order_id"] == order.id
endTo exercise the relay too, call drain/2, which delivers synchronously in
the test process.
Summary
Functions
Asserts that a pending message matching matcher exists and returns the
first one.
Delivers everything currently deliverable in an outbox, synchronously, in the calling process, through the configured relay.
Returns the pending messages of an outbox, oldest first.
Asserts that no pending message matches matcher. See assert_published/3.
Functions
@spec assert_published( atom(), module() | String.t() | (Outboxer.Envelope.t() -> boolean()), keyword() ) :: Outboxer.Envelope.t()
Asserts that a pending message matching matcher exists and returns the
first one.
matcher is a message module (matches on its type), a type string, or a
function taking the envelope and returning a boolean.
assert_published(:orders, MyApp.Events.OrderPlaced)
assert_published(:orders, "order.placed")
assert_published(:orders, &(&1.group_key == "order:1"))
@spec drain(atom(), keyword()) :: %{ delivered: non_neg_integer(), failed: non_neg_integer(), dead: non_neg_integer() }
Delivers everything currently deliverable in an outbox, synchronously, in the calling process, through the configured relay.
Returns %{delivered: n, failed: n, dead: n}. It stops as soon as a pass
delivers nothing, so a message that keeps failing cannot make it loop.
Options
:name- the Outboxer instance, defaultOutboxer.
@spec published(atom(), keyword()) :: [Outboxer.Envelope.t()]
Returns the pending messages of an outbox, oldest first.
Options
:name- the Outboxer instance, defaultOutboxer.:limit- maximum number of messages, default100.
@spec refute_published( atom(), module() | String.t() | (Outboxer.Envelope.t() -> boolean()), keyword() ) :: :ok
Asserts that no pending message matches matcher. See assert_published/3.