Rspec-rails: Negative `have_enqueued_job` does not work as expected with multiple jobs of same kind

Created on 13 Sep 2017  路  3Comments  路  Source: rspec/rspec-rails

Here is my proof of concept:

require 'spec_helper'

class MyJob < ActiveJob::Base
  def perform
    OtherJob.perform_later
    OtherJob.perform_later
  end
end

class OtherJob < ActiveJob::Base
end

describe MyJob do
  subject(:my_job) { MyJob.new }

  it 'enqueues job' do
    expect { my_job.perform }.to have_enqueued_job(OtherJob).at_least(:once)
    expect { my_job.perform }.not_to have_enqueued_job(OtherJob)
  end
end

As I understand, have_enqueued_job checks if job was performed exactly once, so expect { my_job.perform }.to have_enqueued_job(OtherJob) is same as expect { my_job.perform }.to have_enqueued_job(OtherJob).exactly(:once).

But in negative case expect { my_job.perform }.not_to have_enqueued_job(OtherJob) becomes same as expect { my_job.perform }.not_to have_enqueued_job(OtherJob).exactly(:once). So it's quite clear why expect { my_job.perform }.not_to have_enqueued_job(OtherJob) returns true when there is multiple jobs of same kind, but behavior is confusing.

Tried with rspec-rails 3.6.1.

Most helpful comment

I faced same issue. You can hack it with:

expect{ my_job.perform }.to have_enqueued_job(OtherJob).exactly(0).times

All 3 comments

I'm not sure what you're asking here, it seems your code snippet should fail, as expect { my_job.perform }.not_to have_enqueued_job(OtherJob) means you haven't enqueued any jobs, and you have. Expectations don't have any knowledge of each other.

Are you saying it passes? Because thats a bug.

I'm saying that expect { my_job.perform }.to have_enqueued_job(OtherJob).at_least(:once) passes and expect { my_job.perform }.not_to have_enqueued_job(OtherJob) passes

I faced same issue. You can hack it with:

expect{ my_job.perform }.to have_enqueued_job(OtherJob).exactly(0).times
Was this page helpful?
0 / 5 - 0 ratings