Rails 6.1 adds at option to perform_enqueued_jobs test helper


Rails provides perform_enqueued_jobs test helper to perform all enqueued jobs in the given block while testing.

  perform_enqueued_jobs do
    TestJob.perform_later("Hello") # will be performed
  end

  assert_performed_jobs 1

Let’s consider we have a Shift model which has start_time and end_time as timestamps and status to maintain shift’s status. Shift status can be started or finished.

class Shift

  enum status: [:started, :finished]
  after_create :auto_finish_shift

  def auto_finish_shift
    ShiftAutoFinishJob.set(wait_until: end_time).perform_later(id)
  end

end

We have after_save callback to schedule ShiftAutoFinishJob which will wait until shift’s end_time. ShiftAutoFinishJob is used here to automatically finish the shift.

class ShiftAutoFinishJob < ApplicationJob
  queue_as :default

  def perform(shift_id)
    shift = Shift.find(shift_id)
    shift.update status: 'finished'
  end
end
require 'test_helper'

class ShiftTest < ActiveSupport::TestCase
  test "success" do
    perform_enqueued_jobs do
      create :shift, start_time: Time.now, end_time: Time.now + 100, status: 'started'
    end

    assert_performed_jobs 0
  end
end
> rails test TEST=test/models/shift_test
# Running:

F

Failure:
ShiftTest#test_success [/test/models/shift_test.rb:9]:
0 jobs expected, but 1 were performed.
Expected: 0
  Actual: 1

We can see that ShiftAutoFinishJob has been performed. It should not be executed because shift’s end_time is later than the Time.now.

To avoid this, Rails 6.1 has added at option to perform_enqueued_jobs test helper to run only jobs which are scheduled at or before the passed in time.

With Rails 6.1

require 'test_helper'

class ShiftTest < ActiveSupport::TestCase
  test "success" do
    perform_enqueued_jobs(at: Time.now) do
      create :shift, start_time: Time.now, end_time: Time.now + 100, status: 'started'
    end

    assert_performed_jobs 0
  end
end
> rails test TEST=test/models/shift_test
# Running:

.

Finished in 0.579221s, 1.7265 runs/s, 1.7265 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

In the example above, ShiftAutoFinishJob has not been executed because the shift’s end_time is later than the passed in time, i.e. Time.now.