Rails - How do you test ActionMailer sent a specific email in tests

后端 未结 7 2039
面向向阳花
面向向阳花 2020-12-23 12:58

Currently in my tests I do something like this to test if an email is queued to be sent

assert_difference(\'ActionMailer::Base.deliveries.size\', 1) do              


        
相关标签:
7条回答
  • 2020-12-23 13:29

    Here is the best way I've found to do it.

    1) Include the action mailer callbacks plugin like this:

    script/plugin install git://github.com/AnthonyCaliendo/action_mailer_callbacks.git
    

    I don't really use the plugin's main features, but it does provide the nice functionality of being able to figure out which method was used to send an email.

    2) Now you can put some methods in your test_helper.rb like this:

      def assert_sent(method_name)
        assert sent_num_times(method_name) > 0
      end
    
      def assert_not_sent(method_name)
        assert sent_num_times(method_name) == 0
      end
    
      def assert_sent_once(method_name)
        assert sent_num_times(method_name) == 1
      end
    
      def sent_num_times(method_name)
        count = 0
        @emails.each do |email|
          count += 1 if method_name == email.instance_variable_get("@method_name")
        end
        count
      end
    

    3) Now you can write sweet tests like this:

    require 'test_helper'
    class MailingTest < ActionController::IntegrationTest
    
      def setup
        @emails = ActionMailer::Base.deliveries
        @emails.clear
      end
    
      test "should send a mailing" do
        assert_difference "Mailing.count", 1 do
          feeds(:feed1).generate_mailing
        end
    
        assert_sent_once "broadcast"
        assert_not_sent "failed_mailing"
      end
    end
    

    Here "broadcast" and "mailing_failed" are the names of the methods in my ActionMailer::Base class. These are the ones you normally use by calling Mailer.deliver_broadcast(some_data) or Mailer.deliver_failed_mailing(some_data) etc. That's it!

    0 讨论(0)
提交回复
热议问题