Testing Emails

In , let’s add a test:

require "test_helper"
class ProductTest < ActiveSupport::TestCase
include ActionMailer::TestHelper
test "sends email notifications when back in stock" do
product = products(:tshirt)
# Set product out of stock
product.update(inventory_count: 0)
assert_emails 2 do
product.update(inventory_count: 99)
end
end
end

Let’s break down what this test is doing.

First, we include the Action Mailer test helpers so we can monitor emails sent during the test.

The tshirt fixture is loaded using the products() fixture helper and returns the Active Record object for that record. Each fixture generates a helper in the test suite to make it easy to reference fixtures by name since their database IDs may be different each run.

Then we ensure the tshirt is out of stock by updating it’s inventory to 0.

Next, we use assert_emails to ensure 2 emails were generated by the code inside the block. To trigger the emails, we update the product’s inventory count inside the block. This triggers the notify_subscribers callback in the Product model to send emails. Once that’s done executing, assert_emails counts the emails and ensures it matches the expected count.

We can run the test suite with bin/rails test or an individual test file by passing the filename.

Terminal window
$ bin/rails test test/models/product_test.rb
Running 1 tests in a single process (parallelization threshold is 50)
Run options: --seed 3556
# Running:
.
Finished in 0.343842s, 2.9083 runs/s, 5.8166 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips

Our test passes!

Rails also generated an example test for ProductMailer at . Let’s update it to make it also pass.

require "test_helper"
class ProductMailerTest < ActionMailer::TestCase
test "in_stock" do
mail = ProductMailer.with(product: products(:tshirt), subscriber: subscribers(:david)).in_stock
assert_equal "In stock", mail.subject
assert_equal [ "david@example.org" ], mail.to
assert_equal [ "from@example.com" ], mail.from
assert_match "Good news!", mail.body.encoded
end
end

Let’s run the entire test suite now and ensure all the tests pass.

Terminal window
$ bin/rails test
Running 2 tests in a single process (parallelization threshold is 50)
Run options: --seed 16302
# Running:
..
Finished in 0.665856s, 3.0037 runs/s, 10.5128 assertions/s.
2 runs, 7 assertions, 0 failures, 0 errors, 0 skips

You can use this as a starting place to continue building out a test suite with full coverage of the application features.

Learn more about Testing Rails Applications

Proudly built by Evil Martians based on the Rails Guides.
Files
Preparing Environment
  • Preparing Ruby runtime
  • Prepare development database