mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
e35b98e6f5
Follows the same pattern as controllers and jobs. Exceptions raised in delivery jobs (enqueued by `#deliver_later`) are also delegated to the mailer's rescue_from handlers, so you can handle the DeserializationError raised by delivery jobs: ```ruby class MyMailer < ApplicationMailer rescue_from ActiveJob::DeserializationError do … end ``` ActiveSupport::Rescuable polish: * Add the `rescue_with_handler` class method so exceptions may be handled at the class level without requiring an instance. * Rationalize `exception.cause` handling. If no handler matches the exception, fall back to the handler that matches its cause. * Handle exceptions raised elsewhere. Pass `object: …` to execute the `rescue_from` handler (e.g. a method call or a block to instance_exec) against a different object. Defaults to `self`.
153 lines
5.1 KiB
Ruby
153 lines
5.1 KiB
Ruby
require 'abstract_unit'
|
|
require 'active_job'
|
|
require 'mailers/delayed_mailer'
|
|
|
|
class MessageDeliveryTest < ActiveSupport::TestCase
|
|
include ActiveJob::TestHelper
|
|
|
|
setup do
|
|
@previous_logger = ActiveJob::Base.logger
|
|
@previous_delivery_method = ActionMailer::Base.delivery_method
|
|
@previous_deliver_later_queue_name = ActionMailer::Base.deliver_later_queue_name
|
|
ActionMailer::Base.deliver_later_queue_name = :test_queue
|
|
ActionMailer::Base.delivery_method = :test
|
|
ActiveJob::Base.logger = Logger.new(nil)
|
|
ActionMailer::Base.deliveries.clear
|
|
ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
|
|
ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
|
|
|
|
DelayedMailer.last_error = nil
|
|
DelayedMailer.last_rescue_from_instance = nil
|
|
|
|
@mail = DelayedMailer.test_message(1, 2, 3)
|
|
end
|
|
|
|
teardown do
|
|
ActiveJob::Base.logger = @previous_logger
|
|
ActionMailer::Base.delivery_method = @previous_delivery_method
|
|
ActionMailer::Base.deliver_later_queue_name = @previous_deliver_later_queue_name
|
|
|
|
DelayedMailer.last_error = nil
|
|
DelayedMailer.last_rescue_from_instance = nil
|
|
end
|
|
|
|
test 'should have a message' do
|
|
assert @mail.message
|
|
end
|
|
|
|
test 'its message should be a Mail::Message' do
|
|
assert_equal Mail::Message , @mail.message.class
|
|
end
|
|
|
|
test 'should respond to .deliver_later' do
|
|
assert_respond_to @mail, :deliver_later
|
|
end
|
|
|
|
test 'should respond to .deliver_later!' do
|
|
assert_respond_to @mail, :deliver_later!
|
|
end
|
|
|
|
test 'should respond to .deliver_now' do
|
|
assert_respond_to @mail, :deliver_now
|
|
end
|
|
|
|
test 'should respond to .deliver_now!' do
|
|
assert_respond_to @mail, :deliver_now!
|
|
end
|
|
|
|
def test_should_enqueue_and_run_correctly_in_activejob
|
|
@mail.deliver_later!
|
|
assert_equal 1, ActionMailer::Base.deliveries.size
|
|
ensure
|
|
ActionMailer::Base.deliveries.clear
|
|
end
|
|
|
|
test 'should enqueue the email with :deliver_now delivery method' do
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do
|
|
@mail.deliver_later
|
|
end
|
|
end
|
|
|
|
test 'should enqueue the email with :deliver_now! delivery method' do
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now!', 1, 2, 3]) do
|
|
@mail.deliver_later!
|
|
end
|
|
end
|
|
|
|
test 'should enqueue a delivery with a delay' do
|
|
travel_to Time.new(2004, 11, 24, 01, 04, 44) do
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current.to_f+600.seconds, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do
|
|
@mail.deliver_later wait: 600.seconds
|
|
end
|
|
end
|
|
end
|
|
|
|
test 'should enqueue a delivery at a specific time' do
|
|
later_time = Time.now.to_f + 3600
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, at: later_time, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do
|
|
@mail.deliver_later wait_until: later_time
|
|
end
|
|
end
|
|
|
|
test 'should enqueue the job on the correct queue' do
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], queue: "test_queue") do
|
|
@mail.deliver_later
|
|
end
|
|
end
|
|
|
|
test 'can override the queue when enqueuing mail' do
|
|
assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], queue: "another_queue") do
|
|
@mail.deliver_later(queue: :another_queue)
|
|
end
|
|
end
|
|
|
|
test 'deliver_later after accessing the message is disallowed' do
|
|
@mail.message # Load the message, which calls the mailer method.
|
|
|
|
assert_raise RuntimeError do
|
|
@mail.deliver_later
|
|
end
|
|
end
|
|
|
|
test 'job delegates error handling to mailer' do
|
|
# Superclass not rescued by mailer's rescue_from RuntimeError
|
|
message = DelayedMailer.test_raise('StandardError')
|
|
assert_raise(StandardError) { message.deliver_later }
|
|
assert_nil DelayedMailer.last_error
|
|
assert_nil DelayedMailer.last_rescue_from_instance
|
|
|
|
# Rescued by mailer's rescue_from RuntimeError
|
|
message = DelayedMailer.test_raise('DelayedMailerError')
|
|
assert_nothing_raised { message.deliver_later }
|
|
assert_equal 'boom', DelayedMailer.last_error.message
|
|
assert_kind_of DelayedMailer, DelayedMailer.last_rescue_from_instance
|
|
end
|
|
|
|
class DeserializationErrorFixture
|
|
include GlobalID::Identification
|
|
|
|
def self.find(id)
|
|
raise 'boom, missing find'
|
|
end
|
|
|
|
attr_reader :id
|
|
def initialize(id = 1)
|
|
@id = id
|
|
end
|
|
|
|
def to_global_id(options = {})
|
|
super app: 'foo'
|
|
end
|
|
end
|
|
|
|
test 'job delegates deserialization errors to mailer class' do
|
|
# Inject an argument that can't be deserialized.
|
|
message = DelayedMailer.test_message(DeserializationErrorFixture.new)
|
|
|
|
# DeserializationError is raised, rescued, and delegated to the handler
|
|
# on the mailer class.
|
|
assert_nothing_raised { message.deliver_later }
|
|
assert_equal DelayedMailer, DelayedMailer.last_rescue_from_instance
|
|
assert_equal 'Error while trying to deserialize arguments: boom, missing find', DelayedMailer.last_error.message
|
|
end
|
|
end
|