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
:testadapter in theensureblock.
Further reading
Posted by Felix Eschey to makandra dev (2025-12-10 15:52)