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 endend
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.
$ bin/rails test test/models/product_test.rbRunning 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 endend
Let’s run the entire test suite now and ensure all the tests pass.
$ bin/rails testRunning 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
- Preparing Ruby runtime
- Prepare development database