Testing ActiveJob `limits_concurrency` with Solid Queue

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

Felix Eschey