Reputation: 602
I have a custom RSpec matcher that checks that a job is scheduled. It's used like so:
expect { subject }.to schedule_job(TestJob)
schedule_job.rb:
class ScheduleJob
include RSpec::Mocks::ExampleMethods
def initialize(job_class)
@job_class = job_class
end
...
def matches?(proc)
job = double
expect(job_class).to receive(:new).and_return job
expect(Delayed::Job).to receive(:enqueue).with(job)
proc.call
true
end
This works fine for positive matching. But it does not work for negative matching. e.g:
expect { subject }.not_to schedule_job(TestJob) #does not work
For the above to work, the matches?
method needs to return false
when the expectations are not met. The problem is that even if it returns false, the expectations have been created regardless and so the test fails incorrectly.
Any ideas on how to make something like this work?
Upvotes: 3
Views: 2020
Reputation: 692
I had to look for it, but I think it's nicely described here in the rspec documentation
Format (from the docs) for separate logic when using expect.not_to
:
RSpec::Matchers.define :contain do |*expected|
match do |actual|
expected.all? { |e| actual.include?(e) }
end
match_when_negated do |actual|
expected.none? { |e| actual.include?(e) }
end
end
RSpec.describe [1, 2, 3] do
it { is_expected.to contain(1, 2) }
it { is_expected.not_to contain(4, 5, 6) }
# deliberate failures
it { is_expected.to contain(1, 4) }
it { is_expected.not_to contain(1, 4) }
end
Upvotes: 6