I have a job, which I'm currently testing using RSpec:
# app/jobs/do_something_job.rb
class DoSomethingJob < ApplicationJob
def perform(a, b, c)
Service.new(a, b, c).call
end
end
The example file looks this way:
require 'spec_helper'
describe DoSomethingJob do
it do
expect { described_class.perform_later(a, b, c) }.to have_enqueued_job
end
end
That example certainly succeeds, it queues the job no matter what happens within the perform
method body.
Now if I update the Service
class, like removing an argument on its initialize
method, leaving this way:
class Service
def initialize(a, b)
...
end
end
And I don't update the job example, it'll anyway succeed because the job is enqueued. What I'm trying to do is to test the body of DoSomethingJob#perform
executes without errors, without getting on the specifics of Service
itself (it has its own tests).
I tried mocking Service and using expect { ... }.not_to raise_error
, but that fakes the test, since I have to stub the new
and call
methods it receives.
Is there a way to achieve this?
CodePudding user response:
First create a class method on the service so that you don't have to stub an instance:
class Service
def self.call(a, b, c)
new(a, b, c).call
end
end
# app/jobs/do_something_job.rb
class DoSomethingJob < ApplicationJob
def perform(a, b, c)
Service.call(a, b, c)
end
end
Then simply place an expectation on what you want the method to do (in this case call the collaborator) and perform the job immediately:
describe DoSomethingJob do
it "calls Service with a, b, c" do
expect(Service).to receive(:call).with(1, 2, 3).and_call_original
DoSomethingJob.perform_now(1, 2, 3)
end
end