我有一个这样的模型:
class User < ActiveRecord::Base
validates_length_of :name, :in => (2..5)
end
我想测试一下这个验证:
it "should not allow too short name" do
u = User.new(:name => "a")
u.valid?
u.should have(1).error_on(:name)
end
但是它没有测试name
上设置了哪种错误。我想知道,如果是too_short
,too_long
,或者其他一些验证失败了。
我可以在errors数组中查找消息文本,如下所示:
u.errors[:name].should include(I18n.t("activerecord.errors.models.user.attributes.name.too_short"))
但是当我在语言环境文件中设置activerecord.errors.messages.too_short
而不是特定于模型的消息时,这将失败。
那么,是否可以检查出现了哪种错误?
答案 0 :(得分:39)
Rails added an method to query for errors to ActiveModel in late 2011 and Rails v3.2。只需检查相应的错误是否为#added?
:
# An error added manually
record.errors.add :name, :blank
record.errors.added? :name, :blank # => true
# An error added after validation
record.email = 'taken@email.com'
record.valid? # => false
record.errors.added? :email, :taken # => true
请注意,对于参数化的验证(例如:greater_than_or_equal_to
),您还需要传递参数的值。
record.errors.add(:age, :greater_than_or_equal_to, count: 1)
record.errors.added?(:age, :greater_than_or_equal_to, count: 1)
错误由他们的i18n密钥识别。您可以找到相应的密钥,以便在Rails i18n下的任何语言的相应error section文件中查看。
您可以ActiveModel#Error
提出的其他一些漂亮的问题是#empty?
和
#include?(attr)
,以及您可以提出Enumerable
的任何内容。
答案 1 :(得分:12)
我真的不喜欢在错误哈希中查找已翻译的错误消息的想法。在与Rubyists的对话之后,我结束了猴子修补Errors hash,因此它首先保存了未翻译的消息。
module ActiveModel
class Errors
def error_names
@_error_names ||= { }
end
def add_with_save_names(attribute, message = nil, options = {})
message ||= :invalid
if message.is_a?(Proc)
message = message.call
end
error_names[attribute] ||= []
error_names[attribute] << message
add_without_save_names(attribute, message, options)
end
alias_method_chain :add, :save_names
end
end
然后你可以这样测试:
u = User.new(:name => "a")
u.valid?
u.errors.error_names[:name].should include(:too_short)
答案 2 :(得分:5)
我建议检查gem shoulda以处理这些类型的重复验证测试。它补充了RSpec或Test :: Unit,因此您可以编写简明的规范,例如:
describe User do
it { should ensure_length_of(:name).is_at_least(2).is_at_most(5) }
end
答案 3 :(得分:5)
我使用的方法:
it "should not allow too short name" do
u = User.new(:name => "a")
expect{u.save!}.to raise_exception(/Name is too short/)
end
我使用正则表达式来匹配异常消息,因为异常消息中可能有许多验证消息,但我们希望确保它包含与名称太短相关的特定代码段。
这种方法会将您的断言与验证消息结合起来,因此如果您每次修改验证消息,您可能也需要修改您的规范。总的来说,这是断言验证正在完成其工作的一种简单方法。