# `Outboxer.Testing`
[🔗](https://github.com/epinault/outboxer/blob/v0.1.0/lib/outboxer/testing.ex#L1)

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
    end

To exercise the relay too, call `drain/2`, which delivers synchronously in
the test process.

# `assert_published`

```elixir
@spec assert_published(
  atom(),
  module() | String.t() | (Outboxer.Envelope.t() -&gt; 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"))

# `drain`

```elixir
@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, default `Outboxer`.

# `published`

```elixir
@spec published(atom(), keyword()) :: [Outboxer.Envelope.t()]
```

Returns the pending messages of an outbox, oldest first.

## Options

  * `:name` - the Outboxer instance, default `Outboxer`.
  * `:limit` - maximum number of messages, default `100`.

# `refute_published`

```elixir
@spec refute_published(
  atom(),
  module() | String.t() | (Outboxer.Envelope.t() -&gt; boolean()),
  keyword()
) ::
  :ok
```

Asserts that no pending message matches `matcher`. See `assert_published/3`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
