Blog

Thoughts from my daily grind

Testing the Phoenix Elixir Mailer - Swoosh

Posted by Ziyan Junaideen |Published: 06 September 2025 |Category: Elixir Phoenix
Test Mailer |

Automated tests are an integral part of the software development lifecycle. They help us sleep at night, so that an update will not break the system. I don't think anyone would fancy working under stress on a weekend because of a bug they shipped on Friday evening,

While many write tests for complicated functions and behaviours, I often find people skip mailers. While I have done this myself, you should at least be able to test critical and time-sensitive emails.

Here is a simple example of how you can test your Phoenix Mailers.

Background

I am assuming the following:

  • You are on an Elixir Phoenix code base
  • You have configured Oban for job processing
  • You have configured Swoosh as the mailer
  • Your mailers are utilizing Oban jobs for delivering mail

Given that these assumptions are valid, this solution should work fine for you.

The Configuration

You'll need to set up Swoosh in the test environment like that. You may need to customize the mailer to your needs, but the following is the bare minimum for this post.

# lib/jdeen/mailer.ex
defmodule JDeen.Mailer do
  use Swoosh.Mailer, otp_app: :sample
end
# config/test.exs
config :jdeen, JDeen.Mailer,
  adapter: Swoosh.Adapters.Test

The Test

Assume you have to send a notification to a customer about

defmodule JDeen.Notifiers.NewInvoiceNotification do
  @moduledoc false
  use JDeen.DataCase, async: true
  import Swoosh.TestAssertions

  setup do
    customer = JDeen.ConsumerFixtures.customer()

    invoice =
      JDeen.BillingFixtures.invoice(%{customer_id: customer_id})

    %{
      customer: customer,
      invoice: invoice
    }
  end

  test "sends the new invoice email with a link to the PDF download", %{
    invoice: invoice
  } do
    job = %Oban.Job{args: %{"inovice_id" => invoice.id}}
    JDeen.Notifiers.NewInvoiceNotification.perform(job)

    assert_email_sent(fn email ->
      assert email.text_body =~ customer.first_name
      assert email.text_body =~ invoice.id
      assert email.text_body =~ JDeen.Financial.format_currency(invoice.amount_cents, invoice.amount_currency)
      assert email.text_body =~ JDeen.Billing.url(invoice, :pdf)
    end)
  end
end

As you can see, I am manually triggering the Oban job, which in turn would enqueue the mail. Then we can use assert_email_sent. If you are expecting multiple emails to be sent, there is assert_emails_sent. But this is just the test for this particular mailer.

References

Conclusion

Swoosh and Phoenix make it easy to test the mailer. If you are using CoPilot like me, it would have highlighted some weird code. I hope this helped you in your journey.

About the Author

Ziyan Junaideen -

Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.

Comments