在我的rails项目中写了一个自定义验证器,并希望编写一个测试,以便将nil
传递给记录。
验证码
class FutureValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value == nil
record.errors[attribute] << "can't be nil"
elsif value <= Time.now
record.errors[attribute] << (options[:message] || "can't be in the past!")
end
end
end
可能的测试
test "future validator rejects nil values" do
@obj.future = nil
assert_includes @obj.errors
end
我不仅要编写一个检查assert_not @obj.valid?
但实际证明错误消息正在传回的测试。如果那个问得太多我会知道错误消息会回来,但目前我的测试不起作用。
它正在返回
ArgumentError:参数数量错误(1为2..3)
更新 接近绿色测试
test "future validator rejects nil values" do
@obj.future = nil
@obj.valid?
assert_includes @obj.errors.messages, {future: ["can't be nil"]}
end
正在回归
FutureValidatorTest#test_future_validator_rejects_nil_values [/Users/rwdonnard/WorkSpace/charter-pay-api/test/models/future_validator_test.rb:42]: 预期{:future =&gt; [“不能为零”]}包含{:future =&gt; [“不能为零”]}。
答案 0 :(得分:3)
问题似乎是你测试你的类的方式,很可能从assert_includes
引发异常。 assert_includes
期望至少有2个参数,第一个是集合,第二个是您希望包含的对象,在您的情况下是一个错误数组和您期望的错误。如果您没有填充@obj.errors
集合,那么您的测试也会失败,需要致电@obj.valid?
您的测试应如下所示:
test "future validator rejects nil values" do
@obj.future = nil
@obj.valid?
assert_includes @obj.errors.messages, { future: ["can't be nil"] }
end
这样,无论其他验证如何,都要确保future.nil?
模型无效。
我还建议你不要检查你的自定义验证器是否存在,因为Rails已经为此提供了一种方法。您可以让验证器看起来像这样:
class FutureValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value <= Time.now
record.errors[attribute] << (options[:message] || "can't be in the past!")
end
end
end
并在您的模型中设置验证,如下所示:
class SomeClass < ActiveRecord::Base
validates :future, presence: true, future: true
end
您还可以简化测试,例如:
test "is invalid with nil future date" do
@obj.future = nil
@obj.valid?
assert_includes @obj.errors.messages[:future], "can't be nil"
end
test "future validator rejects past dates" do
@obj.future = Date.new(1987, 1, 1)
@obj.valid?
assert_includes @obj.errors.messages[:future], "can't be in the past!"
end