Skip to content
This repository was archived by the owner on May 17, 2026. It is now read-only.

Test Architecture

Tom Giles edited this page Dec 1, 2021 · 4 revisions

This document is currently in draft, and will be expanded further.

ActiveJob

This application has a large number of asynchronous jobs which require a complex setup and add a large overhead to each test. When running feature or integration tests we should prefer expectations around tests being enqueued with the correct values rather than running the tests themselves. This makes the tests less fragile and more independent. Given that jobs also run asynchronously we should write our expectations to test that the application is in the correct state with the assumption that the job is still to run.

Example

When testing a user sign-up feature, when the sign up form has been filled in correctly, the expectations should be that the user is redirected to the correct page, the database is updated and an email job is enqueued. The next test should not invoke the email job, but instead create a signed_up user and then access their confirmation page. A third test should create a new confirmed user and then sign in. No jobs need to be run. The job class itself should be tested separately.

Code

To test a job has been enqueued wrap the actions you expect to enqueue it in a block:

expect do
  # Some actions
end.to have_enqueued_job(JobClass).with(some_model, attribute: "some value").exactly(:once)

If this is not possible and some jobs will have to run, we should ensure that only jobs specifically relevant to that test are run. This can be achieved by naming the tests in a perform_enqueued_jobs block:

perform_enqueued_jobs(only: [JobClass, AnotherJob]) 
 # Call jobs here
end

If you are not sure precisely which job classes will need to be called, restrict this to the jobs you know will be called. If the test fails, check your test.log for enqueued jobs, and add each required one to the list. The rails_helper.rb makes sure that the :test queue adaptor is always used and the queue is cleared after each test.

config.before do
  ActiveJob::Base.queue_adapter = :test
end

config.after do
  clear_enqueued_jobs
end

If you want a test performed immediately please call ActiveJob::Base.queue_adapter = :inline in your test (or a before block).

Clone this wiki locally