我正在尝试测试这段代码:
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
如何找出库正在寻找的参数类型?
答案 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
将抓住MockRecordInvalid
,MockRecordInvalid.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))