Skip to content

Make sure that negative matcher fails on multiple enqueues of the same kind #1871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions lib/rspec/rails/matchers/active_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def initialize
@queue = nil
@at = nil
@block = Proc.new {}
set_expected_number(:exactly, 1)
@using_default_expected_number = true
silently_set_expected_number(:exactly, 1)
end

def with(*args, &block)
Expand Down Expand Up @@ -78,7 +79,7 @@ def failure_message
end

def failure_message_when_negated
"expected not to enqueue #{base_message}"
"expected not to enqueue #{base_negative_message}"
end

def message_expectation_modifier
Expand All @@ -95,6 +96,10 @@ def supports_block_expectations?

private

def using_default_expected_number?
@using_default_expected_number
end

def check(jobs)
@matching_jobs, @unmatching_jobs = jobs.partition do |job|
if arguments_match?(job) && other_attributes_match?(job)
Expand All @@ -115,7 +120,19 @@ def check(jobs)
end

def base_message
"#{message_expectation_modifier} #{@expected_number} jobs,".tap do |msg|
message_with_base_info("#{message_expectation_modifier} #{@expected_number} jobs,")
end

def base_negative_message
if @expectation_type == :exactly && @expected_number.zero?
message_with_base_info("job,")
else
base_message
end
end

def message_with_base_info(intro_message)
intro_message.dup.tap do |msg|
msg << " with #{@args}," if @args.any?
msg << " on queue #{@queue}," if @queue
msg << " at #{@at}," if @at
Expand Down Expand Up @@ -156,6 +173,11 @@ def serialized_attributes
end

def set_expected_number(relativity, count)
@using_default_expected_number = false
silently_set_expected_number(relativity, count)
end

def silently_set_expected_number(relativity, count)
@expectation_type = relativity
@expected_number = case count
when :once then 1
Expand Down Expand Up @@ -187,6 +209,15 @@ def matches?(proc)

check(in_block_jobs)
end

def does_not_match?(proc)
if using_default_expected_number?
silently_set_expected_number(:exactly, 0)
matches?(proc)
else
!matches?(proc)
end
end
end

# @private
Expand Down
46 changes: 45 additions & 1 deletion spec/rspec/rails/matchers/active_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,34 @@ def self.name; "LoggingJob"; end
}.to raise_error(/expected to enqueue exactly 1 jobs, but enqueued 2/)
end


it "shows correct fail message when negated with at_least matcher" do
expect {
expect {
heavy_lifting_job.perform_later
heavy_lifting_job.perform_later
}.not_to have_enqueued_job.at_least(2)
}.to raise_error(/expected not to enqueue at least 2 jobs, but enqueued 2/)
end

it "shows correct fail message when negated with at_most matcher" do
expect {
expect {
heavy_lifting_job.perform_later
heavy_lifting_job.perform_later
}.not_to have_enqueued_job.at_most(2)
}.to raise_error(/expected not to enqueue at most 2 jobs, but enqueued 2/)
end

it "fails when too many jobs enqueued in negated form" do
expect {
expect {
heavy_lifting_job.perform_later
heavy_lifting_job.perform_later
}.not_to have_enqueued_job.exactly(2)
}.to raise_error(/expected not to enqueue exactly 2 jobs, but enqueued 2/)
end

it "reports correct number in fail error message" do
heavy_lifting_job.perform_later
expect {
Expand All @@ -116,7 +144,7 @@ def self.name; "LoggingJob"; end
it "fails when negated and job is enqueued" do
expect {
expect { heavy_lifting_job.perform_later }.not_to have_enqueued_job
}.to raise_error(/expected not to enqueue exactly 1 jobs, but enqueued 1/)
}.to raise_error(/expected not to enqueue job, but enqueued 1/)
end

it "passes with job name" do
Expand All @@ -134,6 +162,22 @@ def self.name; "LoggingJob"; end
}.to have_enqueued_job(hello_job).and have_enqueued_job(logging_job)
end

it "passes with multiple jobs of the same kind and different expected count when negated" do
expect {
hello_job.perform_later
hello_job.perform_later
}.not_to have_enqueued_job.once
end

it "fails with multiple same type jobs when negated" do
expect {
expect {
hello_job.perform_later
hello_job.perform_later
}.not_to have_enqueued_job
}.to raise_error(/expected not to enqueue job, but enqueued 2/)
end

it "passes with :once count" do
expect {
hello_job.perform_later
Expand Down