bo-oz
bo-oz

Reputation: 2872

How to test the rescue block in my model callback in RSpec?

I have an after_save method in my model, to call some background task. Since this task is depending on another server being up, I thought it was a nice idea to create a fallback to perform the task on the main thread when the call to the other server fails.

This is basically the callback:

  def send_email
    MyJob.perform_async(self.id)
  rescue Errno::ECONNREFUSED
    MyJob.new.perform(self.id)
  end

Now I'd like to test this bahavior. I tried by mocking the MyJob and raising the exception on the perfrom_async method. But how do I test that perform is being called on the instance?

I already tried:

it "should use fallback to send e-mail after create when faktory is down" do
  job = class_double("MyJob").
  as_stubbed_const(:transfer_nested_constants => true)

  allow(job).to receive(:perform_async) { raise Errno::ECONNREFUSED }
  expect_any_instance_of(job).to receive(:perform)
  company_opt_out
end

Thanks

Upvotes: 0

Views: 540

Answers (2)

Paul Byrne
Paul Byrne

Reputation: 1615

Try to not overload the it block too much when you write the test as they become hard to read when you or another developer comes back to it later.

  let(:job_instance) { instance_double(MyJob, perform: "Performing now") }

  before do
    allow(MyJob).to receive(:perform_async).and_return("Performing later")
    allow(MyJob).to receive(:new).and_return(job_instance)
  end

  it "performs the job later" do
    expect(send_email).to eq("Performing later")
  end

  context "when a network error is raised" do
    before { allow(MyJob).to receive(:perform_async).and_raise(Errno::ECONNREFUSED) }

    it "performs the job now" do
      expect(send_email).to eq("Performing now")
    end
  end

Upvotes: 1

Saiqul Haq
Saiqul Haq

Reputation: 2397

no need to stub MyJob class

it "should use fallback to send e-mail after create when faktory is down" do
  allow(MyJob).to receive(:perform_async).and_raise(Errno::ECONNREFUSED)
  expect_any_instance_of(MyJob).to receive(:perform)
  company_opt_out
end

but make sure your company_opt_out calls send_email method

Upvotes: 1

Related Questions