如何创建ActiveRecord :: RecordInvalid进行测试?

时间:2014-09-24 18:54:54

标签: ruby-on-rails activerecord rspec

我正在尝试测试这段代码:

def error_from_exception(ex)
  if ex.is_a?(ActiveRecord::RecordInvalid)
...

要进入if块,我需要传入正确的ex参数。

如何创建ActiveRecord :: RecordInvalid?

使用rspec,我正在尝试这样做:

context 'exception is ActiveRecord::RecordInvalid' do
  it 'returns the validation error' do
    begin
      raise ActiveRecord::RecordInvalid
    rescue Exception => ex
      binding.pry
      ###
      # From my pry session:
      # $ ex
      # $ <ArgumentError: wrong number of arguments (0 for 1)>
      # $ ex.class
      # $ ArgumentError < StandardError
      ###
    end


  end
end

如何找出库正在寻找的参数类型?

RecordInvalid link

6 个答案:

答案 0 :(得分:4)

编辑:现在可以在Rails 5.1.1中使用。此提交后不再需要记录参数:https://github.com/rails/rails/commit/4ff626cac901b41f86646dab1939d2a95b2d26bd

如果您使用的是5.1.1下的Rails版本,请参阅以下原始答案:

似乎不可能自己提出ActiveRecord::RecordInvalid。如果查看ActiveRecord::RecordInvalid的源代码,初始化时需要记录:

class RecordInvalid < ActiveRecordError
  attr_reader :record # :nodoc:
  def initialize(record) # :nodoc:
    @record = record
    ...
  end
end

(来源:https://github.com/rails/rails/blob/master/activerecord/lib/active_record/validations.rb

你可以做的就是简单地创建一个无效的实际记录并尝试使用save!保存它(例如在需要User.new.save!时调用User.name )。但是,请记住,如果您使用的模型发生更改并且在测试中变为有效,则可能在将来成为问题(不再需要User.name)。

答案 1 :(得分:1)

我需要做类似的事情来测试我的代码对ActiveRecord::RecordInvalid的处理。我想做

allow(mock_ar_object).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)

但是当RSpec尝试实例化ArgumentError: wrong number of arguments (0 for 1)时,这会给RecordInvalid

相反,我编写了一个RecordInvalid子类并覆盖initialize,如下所示:

class MockRecordInvalid < ActiveRecord::RecordInvalid
  def initialize
  end
end

allow(mock_ar_object).to receive(:save!).and_raise(MockRecordInvalid)

然后rescue ActiveRecord::RecordInvalid将抓住MockRecordInvalidMockRecordInvalid.new.is_a?(ActiveRecord::RecordInvalid)抓住true

答案 2 :(得分:1)

以上方法均不适用于我,因此我在做规格时终于做了以下工作:

class InvalidRecord
  include ActiveModel::Model
end


raise ActiveRecord::RecordInvalid.new(InvalidRecord.new)

希望有帮助!

答案 3 :(得分:0)

ActiveRecord :: RecordInvalid需要创建一个对象。 如果您只想测试异常本身,请尝试:

null_object = double.as_null_object
ActiveRecord::RecordInvalid.new(null_object)

在这里理解double as null对象(https://www.relishapp.com/rspec/rspec-mocks/v/2-6/docs/method-stubs/as-null-object

答案 4 :(得分:0)

我正在使用update_attribute(attr,'value')而不是保存!并且我可以如下模拟update_attribute方法:

expect(mock_object).to receive(:update_attribute).with(attr, 'value').and_raise(ActiveRecord::RecordInvalid)

答案 5 :(得分:0)

我们可以像这样将其存入模型,

ModelName.any_instance.stubs(<method_name>).raises(ActiveRecord::RecordInvalid.new(record))

示例:

Post.any_instance.stubs(:save!).raises(ActiveRecord::RecordInvalid.new(post))