Email is usually the least tested part of a product because the test would send a real message to a real inbox. The workaround is a test doubles pattern that is easy to get wrong.

Assert on the intent, not the transport

Most suites mock the email client and assert that send was called. That passes while the template is broken. The useful assertion is on the rendered output: subject, recipient, and the presence of the token or link that the flow depends on.

Render in the test

Render the template with the same code path as production, then check the HTML and the text part both contain the expected URL. This catches the failure that matters most: a link that lost its base URL and now points at localhost.

Keep one real send per release

Mocks cannot catch DNS, authentication, or provider rejection. One real send per release to an internal address, with the headers checked for dkim=pass and a matching return-path, covers the gap that unit tests structurally cannot.

The detail that finds regressions

Snapshot the rendered message body and diff it in CI. Template edits that break variable substitution show up as a diff instead of as a customer complaint, and the diff is small enough to review.

Volanea exposes a render endpoint that returns the exact subject and body for given variables, so tests can assert on the real output.