Skip to content

New ActiveJob is not counted when other job executed #2668

Closed
@mkllnk

Description

@mkllnk

What Ruby, Rails and RSpec versions are you using?

Ruby version: ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux]
Rails version: Rails 7.0.4.3
RSpec version: RSpec 3.12

  • rspec-core 3.12.1
  • rspec-expectations 3.12.2
  • rspec-mocks 3.12.3
  • rspec-rails 6.0.1
  • rspec-support 3.12.0

Observed behaviour

Consider this example:

    ReportJob.perform_later(*report_args)

    expect {
      perform_enqueued_jobs(only: ReportJob)
    }.to enqueue_job(ActionMailer::MailDeliveryJob)

The ReportJob sends an email and this test should pass but fails:

     Failure/Error:
       expect {
         perform_enqueued_jobs(only: ReportJob)
       }.to enqueue_job(ActionMailer::MailDeliveryJob)
     
       expected to enqueue exactly 1 jobs, but enqueued 0

I found the reason in the matcher simply taking the count of pre-existing jobs and dropping them off the queue when comparing:

original_enqueued_jobs_count = queue_adapter.enqueued_jobs.count
proc.call
in_block_jobs = queue_adapter.enqueued_jobs.drop(original_enqueued_jobs_count)

Expected behaviour

I expected the matcher to only ignore pre-existing jobs and not newly generated jobs. I would also have understood if the matcher would only look for MailDeliveryJobs but the types of jobs executed and enqueued are different here.

I saw in the original pull request that it was counting only the requested job type but I'm wondering if we could actually remember the previous jobs (with id) and drop only those off the queue. I'm not familiar with the adapters but I was wondering if this would work:

            original_enqueued_jobs = queue_adapter.enqueued_jobs
            proc.call
            in_block_jobs = queue_adapter.enqueued_jobs - original_enqueued_jobs

It may have performance implications.

Can you provide an example app?

I hope that the above examples are easy enough but let me know if I need to create an app for this. Maybe more useful, here's an (untested) spec:

diff --git a/spec/rspec/rails/matchers/active_job_spec.rb b/spec/rspec/rails/matchers/active_job_spec.rb
index 38aee9d3..0c24276d 100644
--- a/spec/rspec/rails/matchers/active_job_spec.rb
+++ b/spec/rspec/rails/matchers/active_job_spec.rb
@@ -94,6 +94,14 @@ RSpec.describe "ActiveJob matchers", skip: !RSpec::Rails::FeatureCheck.has_activ
       }.to have_enqueued_job.exactly(1)
     end
 
+    it "counts jobs even when others are removed" do
+      heavy_lifting_job.perform_later
+      expect {
+        perform_enqueued_jobs
+        hello_job.perform_later
+      }.to have_enqueued_job(hello_job)
+    end
+
     it "passes when negated" do
       expect { }.not_to have_enqueued_job
     end

mkllnk@7ecda54

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions