自定义验证器测试 - 包含错误?

时间:2016-04-18 15:35:27

标签: ruby-on-rails ruby validation unit-testing minitest

在我的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; [“不能为零”]}。

1 个答案:

答案 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