Testing ActiveJob `limits_concurrency` with Solid Queue

Updated . Posted . Visible to the public.

The :test adapter doesn't respect limits_concurrency configuration. Switch to :solid_queue adapter in your test to verify blocking behavior.

Job Configuration

class MembershipJob < ApplicationJob
  limits_concurrency(key: ->(membership) { membership })
end

The problem

When using the default test mode for enqueuing jobs, both will be enqueued immediately. However, we actually we want to test that only one of both will be enqueued as the other should have been blocked.

# This doesn't actually test concurrency control
test('enqueues both jobs') do
  MembershipJob.perform_later(membership)
  MembershipJob.perform_later(membership)
  
  assert_enqueued_jobs(2, only: MembershipJob)
  # Both enqueue, but we haven't proven the second will block
end

The solution

The solution is to use the actual solid queue adapter and query for the blocked jobs and the ones ready for execution.

test('limits concurrency second job with same membership is blocked') do
  membership = create_valid_membership(id: 76381)

  ActiveJob::Base.queue_adapter = :solid_queue

  begin
    MembershipJob.perform_later(membership)
    second_blocked_job = MembershipJob.perform_later(membership)

    # Verify blocking behavior
    assert_equal(1, SolidQueue::ReadyExecution.count)
    assert_equal(1, SolidQueue::BlockedExecution.count)
      
    blocked = SolidQueue::BlockedExecution.last
    assert_equal(second_blocked_job.provider_job_id, blocked.job_id)

  ensure
    ActiveJob::Base.queue_adapter = :test # Correctly restore the test adapter
  end
end

Restore the Adapter

Always restore :test adapter in the ensure block.

Further reading

Profile picture of Felix Eschey
Felix Eschey
Last edit
Felix Eschey
Keywords
ruby, on, rails, minitest
License
Source code in this card is licensed under the MIT License.
Posted by Felix Eschey to makandra dev (2025-12-10 15:52)