Reputation: 2678
In my public method #recalculate, calling the private method1
. This method throw exception 'ActiveRecord::StaleObjectError'.
def recalculate
method_1
self.save!
end
private
def method_1
begin
####
####
if self.lock_version == Product.find(self.id).lock_version
Product.where(:id => self.id).update_all(attributes)
else
raise ActiveRecord::StaleObjectError.new(self, "test")
end
rescue ActiveRecord::StaleObjectError => e
if tries < 3
tries += 1
sleep(1 + tries)
self.reload
retry
else
raise Exception.new(timeout.inspect)
end
end
end
Rspec Test case:
it 'if car is updated then ActiveRecord::StaleObjectError should be raised' do
prod_v1 =Product.find(@prod.id)
prod_v2 = Car.find(@prod.id)
prod_v1.recalculate
prod_v1.reload # will make lock_version of prod_v1 to 1
prod_v2.recalculate # howvever lock_version of prod_v2 is still 0.
expect{ prod_v2.send(:method1)}.to raise_error(ActiveRecord::StaleObjectError)
Error:
Failure/Error: expect(prod_v2.send(:method1)).to raise_error(ActiveRecord::StaleObjectError) expected ActiveRecord::StaleObjectError but nothing was raised
Please suggest how to write the unit test case for an exception which is raised in private method.
I have used send
based on the link:
Note: Exception was raised for in the first time because self.lock_version == Product.find(self.id) was false . And in retry self.lock_version == Product.find(self.id) is true so exception is not capture.
Upvotes: 0
Views: 1006
Reputation: 562
Here's a simpler version of what your code is actually doing:
class StaleObjectError < Exception
end
class MyClass
def initialize
@tries = 0
end
def method_1
begin
raise StaleObjectError.new("I'm the more specific exception")
rescue StaleObjectError => e
if @tries < 3
@tries += 1
sleep(1 + @tries)
retry
else
raise Exception.new("I'm the failure case")
end
end
end
end
myObject = MyClass.new
begin
myObject.method_1
rescue Exception => e
# in the error condition, this is always #<Exception: I'm the failure case>
puts e.inspect
end
Which results in
#<Exception: I'm the failure case>
You won't be able to expect the ActiveRecord::StaleObjectError
because you mask it with your rescue else- you've converted the StaleObjectError
into an Exception
If you want to preserve the StaleObjectError
then you can raise e
in your rescue else instead. So to use my example code again:
if @tries < 3
@tries += 1
sleep(1 + @tries)
retry
else
raise e
end
Which would result in
#<StaleObjectError: I'm the more specific exception>
Then your rspec example should be able to expect the code to raise the correct exception type.
Upvotes: 2