当我在模型中添加自定义验证时,RSpec中的模型验证失败

时间:2018-12-05 09:09:40

标签: ruby-on-rails rspec

我有一个带有两个自定义验证规则的模型。当我删除这些规则时,用于模型验证的RSpec将通过。但是,在模型中添加这些验证后,RSpec无法通过之前通过的验证。 如何解决此错误,以及如何为这些自定义验证编写RSpec?

我的模型文件leave.rb

class Leave < ApplicationRecord
  scope :sorted_asc, lambda { order(id: :asc) }
  validates :start_day, :end_day,  :reason, :status, presence: true
  validate :start_day_cant_be_past, :end_day_cant_be_less_than_start_day
  enum category: { 'Sick': 0, 'Leave in Policy': 1, 'Out of Policy': 2 }

  def start_day_cant_be_past
    if start_day < Date.today
      errors.add(:start_day, 'can not be in the past')
    end
  end

  def end_day_cant_be_less_than_start_day
    if end_day < start_day
      errors.add(:end_day, 'can not be less than start day')
    end
  end
end

我的模型leave_spec.rb的RSpec文件

require 'rails_helper'

RSpec.describe Leave, type: :model do
  it { should define_enum_for(:category).with(['Sick', 'Leave in Policy', 'Out of Policy']) }
  it { is_expected.to validate_presence_of(:start_day) }
  it { is_expected.to validate_presence_of(:end_day) }
  it { is_expected.to validate_presence_of(:reason) }
  it { is_expected.to validate_presence_of(:status) }
end

我得到的错误是...

Leave should validate that :start_day cannot be empty/falsy
     Failure/Error: if start_day < Date.today

     NoMethodError:
       undefined method `<' for nil:NilClass

1 个答案:

答案 0 :(得分:1)

您收到错误消息,因为start_daynil。我会向自定义验证人添加防护措施:

def start_day_cant_be_past
  return unless start_day

  if start_day < Date.today
    errors.add(:start_day, 'can not be in the past')
  end
end

def end_day_cant_be_less_than_start_day
  return unless end_day && start_day

  if end_day < start_day
    errors.add(:end_day, 'can not be less than start day')
  end
end

要测试这些自定义验证程序,我将编写常规测试示例,例如:

it 'is invalid with start day in the past' do
  leave = Leave.new(start_day: 2.days.ago)
  expect(leave).to be_invalid
  expect(leave.errors[:start_day]).not_to be_empty
end

it 'is invalid with start day later than end day' do
  leave = Leave.new(start_day: 2.days.ago, start_day: 5.days.ago)
  expect(leave).to be_invalid
  expect(leave.errors[:end_day]).not_to be_empty
end