Matilda Matilda - 1 month ago 32
Ruby Question

RSpec retry throw exception and then return value

I have a retry block

def my_method
app_instances = []
attempts = 0
begin
app_instances = fetch_and_rescan_app_instances(page_n, policy_id, policy_cpath)
rescue Exception
attempts += 1
retry unless attempts > 2
raise Exception
end
page_n += 1
end


where
fetch_and_rescan_app_instances
access the network so can throw an exception.

I want to write an rspec test that it throws an exception first time and doesn't throw an exception second time it gets called, so I can test if the second time it doesn't throw an exception, the my_method won't throw an exeption.

I know i can do
stub(:fetch_and_rescan_app_instances).and_return(1,3)
and first time it returns 1 and second time 3, but I don't know how to do throw an exception first time and return something second time.

Answer

You can calculate the return value in a block:

describe "my_method" do
  before do
    my_instance = ...
    @times_called = 0
    my_instance.stub(:fetch_and_rescan_app_instances).and_return do
      @times_called += 1
      raise Exception if @times_called == 1
    end
  end

  it "raises exception first time method is called" do
    my_instance.my_method().should raise_exception
  end

  it "does not raise an exception the second time method is called" do
    begin
      my_instance.my_method()
    rescue Exception
    end
    my_instance.my_method().should_not raise_exception
  end
end

Note that you should really not be rescuing from Exception, use something more specific. See: Why is it bad style to `rescue Exception => e` in Ruby?

Comments