Testing ActiveJob `limits_concurrency` with Solid Queue

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 }, duration: 10.seconds)
end

The problem

# 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

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)

    # Verify duration configuration (10 seconds)
    blocked = SolidQueue::BlockedExecution.last
    assert_equal(second_blocked_job.provider_job_id, blocked.job_id)
    assert_in_delta(10.seconds.from_now, blocked.expires_at, 1.second)
  ensure
    ActiveJob::Base.queue_adapter = :test # Correctly restore the test adapter
  end
end

This proves: (1) the second job is blocked, (2) the duration parameter is applied correctly.

The duration should match your job's typical execution time plus a safety margin. For jobs averaging 0.12 seconds, 10 seconds provides ample buffer.

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)