RSpec:如何编写单元测试用例以接收在私有方法中引发的异常

时间:2018-10-04 06:34:18

标签: ruby-on-rails ruby ruby-on-rails-3 rspec rspec2

我已为比赛条件实施了乐观锁。为此,我在产品中添加了额外的列lock_version。方法:recalculate正在呼叫专用method_1,然后保存(save!)产品。我不能在私有save!中使用method_1,因为它会使其他事情失败。我不想重组业务逻辑。

#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测试用例:

  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

当我尝试在测试用例之上编写代码时,它将引发异常ActiveRecord::StaleObjectError。但是,我收到类似

的错误
 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 个答案:

答案 0 :(得分:0)

您可以这样写:

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

因为您要挽救异常

请务必检查https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

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

意味着car_v2收到method1时不会调用它,但是会引发ActiveRecord::StaleObjectError类型的异常。这就是为什么您还会收到ArgumentError

的原因

使用rspec,您可以检查特定代码是否引发错误(在您遇到的情况下无法处理->救援...),如下所示:

expect { my_cool_method }.to raise_error(ErrorClass)