RSpec: How to write unit test case to receive an exception which is getting raised in private method

限于喜欢 提交于 2019-12-02 11:25:54

问题


I have implemented Optimistic Locking for Race Condition. For that, I added an extra column lock_version in the Product. Method: recalculate is calling private method_1 then it saves (save!) the product. I can't use save! in private method_1, because it will fail the other things. I don't want to restructure the business logic.

#Product: Model's new field:
    #  lock_version                       :integer(4)      default(0), not null

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(car_v2).to receive(:method1).and_raise(ActiveRecord::StaleObjectError)
  end

When I try to write above the test case, then it should raise an Exception ActiveRecord::StaleObjectError. However, I am getting an error like

 Failure/Error: expect(car_v2).to receive(:set_total_and_buckets_used).and_raise(ActiveRecord::StaleObjectError)
 ArgumentError:
   wrong number of arguments (0 for 2)

回答1:


You could write something like:

expect(ActiveRecord::StaleObjectError).to receive(:new).and_call_original

Because you are rescue-ing the exception

Make sure to check https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

expect(car_v2).to receive(:method1).and_raise(ActiveRecord::StaleObjectError)

Means that when car_v2 receives the method1 you won't call it but you'll raise an exception of type ActiveRecord::StaleObjectError. This is why you also receive the ArgumentError

With rspec you can check that a specific code raises an error (that is not handled in your case it is handled -> rescue...) like this:

expect { my_cool_method }.to raise_error(ErrorClass)


来源:https://stackoverflow.com/questions/52640468/rspec-how-to-write-unit-test-case-to-receive-an-exception-which-is-getting-rais

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!