Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing jobs synchronously #435

Closed
christianrolle opened this issue Oct 26, 2021 · 4 comments
Closed

Testing jobs synchronously #435

christianrolle opened this issue Oct 26, 2021 · 4 comments

Comments

@christianrolle
Copy link

christianrolle commented Oct 26, 2021

The progres this gem makes is amazing! 🚀

For integration tests I want to have expectations no matter how the job is run (synchronously or asynchronously).
How to enforce running the enqueued job right away? I tried with:

before { Rails.application.config.good_job.execution_mode = :inline }
after { Rails.application.config.good_job.execution_mode = :external }
it 'should create a task' do
  expect { run_request }.to(change { Task, :count }.by(1))
end

for something like:

def create
  CreateTaskJob.perform_later task_params
end

The job isn't performed even though the execution mode is :inline.
Don't get me wrong. The job implementation works and in the unit test I just execute the job by #perform_now. But I'd rather like to test its result in the integration test.
Do I misunderstand the mode?
Is there a better approach for running the jobs immediately (synchronously)?

@bensheldon
Copy link
Owner

bensheldon commented Oct 26, 2021

@christianrolle always making progress on this gem 😄

You'll want to assign the entire queue_adapter:

around do |example
  original_adapter = ActiveJob::Base.queue_adapter
  good_job_adapter = GoodJob::Adapter.new(execution_mode: :inline)
  ActiveJob::Base.queue_adapter = good_job_adapter

  example.run
  
  good_job_adapter.shutdown
  ActiveJob::Base.queue_adapter = original_adapter
end

Also, fyi there are some versions of Rails/Rspec that may override the adapter, but I think the above should be fairly bulletproof.

Edit: added #shutdown command to code example.

@morgoth
Copy link
Collaborator

morgoth commented Oct 27, 2021

@christianrolle Isn't the AJ adapter set to test one? https://github.com/rails/rails/blob/main/activejob/lib/active_job/queue_adapters/test_adapter.rb

I believe that's the best way of testing and you can perform jobs by using https://edgeapi.rubyonrails.org/classes/ActiveJob/TestHelper.html#method-i-perform_enqueued_jobs

What's your usecase to use Good Job in tests?

@christianrolle
Copy link
Author

christianrolle commented Nov 10, 2021

@morgoth your're right. We should expect GoodJob to be tested properly. So for for test outcome (testing the systems behavior) it shouldn't matter which AJ job adapter we use.
Thank you.

@christianrolle
Copy link
Author

christianrolle commented Apr 11, 2024

Stumbled across this way of switching off asynchronicity:

# rails_helper.rb
RSpec.configure do |config|
  config.before :example, perform_enqueued: true do
    @old_perform_enqueued_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_jobs
    @old_perform_enqueued_at_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
  end

  config.after :example, perform_enqueued: true do
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = @old_perform_enqueued_at_jobs
  end
end

and then:

it "should perform immediately", :perform_enqueued do
  SomeJob.perform_later  
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants