如果我无法在模型中创建禁止过去日期的对象,如何在过去的日期 Rails 上使用 RSpec 进行测试?

How to test with RSpec on Rails a past date if I cant create an object with past date being prohibited inside the model?

我有一个约会模型,它禁止使用过去的日期创建对象,或者如果字段日期是过去的则禁止更新。

class Appointment < ApplicationRecord
  belongs_to :user

  ...

  validate :not_past, on: [:create, :update]

  private

  ...

  def not_past
    if day.past?
      errors.add(:day, '...')
    end
  end
end

但我需要使用 RSpec 制作一个测试文件来测试如果字段日期是过去的日期是否真的无法编辑。

require 'rails_helper'

RSpec.describe Appointment, type: :model do
...
  it 'Cannot be edited if the date has past' do
    @user = User.last
    r = Appointment.new
    r.day = (Time.now - 2.days).strftime("%d/%m/%Y")
    r.hour = "10:00"
    r.description = "Some Description"
    r.duration = 1.0
    r.user = @user
    r.save!
    x = Appointment.last
    x.description = "Other"
    expect(x.save).to be_falsey
  end
  ...
end

麻烦的是,由于错误禁止创建过去一天的 Appointment 对象,因此测试无法准确。

我应该怎么做才能强制,甚至可能制作一个带有过去日期的假对象,以便我最终可以测试它?

您可以使用 update_attribute 来跳过验证。

  it 'Cannot be edited if the date has past' do
    @user = User.last
    r = Appointment.new
    r.day = (Time.now - 2.days).strftime("%d/%m/%Y")
    r.hour = "10:00"
    r.description = "Some Description"
    r.duration = 1.0
    r.user = @user
    r.save!
    x = Appointment.last
    x.description = "Other"

    r.update_attribute(:day, (Time.now - 2.days).strftime("%d/%m/%Y"))

    expect(x.save).to be_falsey
  end

您的测试中也有很多噪音(未断言的数据),您应该通过例如创建辅助函数或使用 factories.

it 'Cannot be edited if the date has past' do
  appointment = create_appointment
  appointment.update_attribute(:day, (Time.now - 2.days).strftime("%d/%m/%Y"))

  appointment.description = 'new'

  assert(appointment.valid?).to eq false
end

def create_appointment
  Appointment.create!(
    day: Time.now.strftime("%d/%m/%Y"),
    hour: '10:00',
    description: 'description',
    duration: 1.0,
    user: User.last
  )
end

您还测试了 falsey,它也将匹配 nil 值。在这种情况下,您要做的是使用 eq false.

测试 false