【问题标题】:RSpec failing - date comparisonRSpec 失败 - 日期比较
【发布时间】:2021-05-25 12:02:46
【问题描述】:

所以我有一个失败的 RSpec 测试,我确信测试是问题所在,因为从功能的角度来看它可以正常工作。

简而言之,end_time 不应该是 before_start 时间。保存模型后,它可以正常工作,只有 RSpec 失败,任何指针都将不胜感激

chain_plan_spec.rb

# frozen_string_literal: true

# == Schema Information
#
# Table name: chain_plans
#
#  id         :bigint           not null, primary key
#  end_time   :datetime
#  start_time :datetime
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  faction_id :bigint           not null
#
# Indexes
#
#  index_chain_plans_on_faction_id  (faction_id)
#
# Foreign Keys
#
#  fk_rails_...  (faction_id => factions.id)
#
require 'rails_helper'
RSpec.describe ChainPlan, type: :model do
  it { is_expected.to validate_presence_of :start_time }
  it { is_expected.to validate_presence_of :end_time }
  it { is_expected.to validate_presence_of :faction }

  it 'does not have a start date/time before an end date/time' do
    cp = described_class.new
    cp.start_time = Date.now
    cp.end_time = cp.start - 1.minute
    cp.save!

    expect(cp).not_to be_valid
  end
  # TODO: end is 0 minute
  # TODO start is 0 minute
end

chain_plan.rb

# frozen_string_literal: true

# == Schema Information
#
# Table name: chain_plans
#
#  id         :bigint           not null, primary key
#  end_time   :datetime
#  start_time :datetime
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  faction_id :bigint           not null
#
# Indexes
#
#  index_chain_plans_on_faction_id  (faction_id)
#
# Foreign Keys
#
#  fk_rails_...  (faction_id => factions.id)
#
class ChainPlan < ApplicationRecord
  belongs_to :faction
  has_many :chain_plan_slots
  validates :start_time, presence: { on: :create, message: "can't be blank" }
  validates :end_time, presence: { on: :create, message: "can't be blank" }
  validates :faction, presence: { on: :create, message: "can't be blank" }
  validate :end_date_after_start_date?

  private

  def end_date_after_start_date?
    return if end_time.blank? || start_time.blank?

    errors.add(:end_date, 'must be after the start date') if end_time < start_time
  end
end

【问题讨论】:

    标签: ruby-on-rails rspec rspec-rails


    【解决方案1】:

    测试验证时不要使用expect(object).not_to be_validexpect(object).to be_valid。这只是假阳性和阴性结果的一个秘诀,因为您实际上并不是在测试单一行为,而是在同时测试每一个验证以及您的测试设置。

    RSpec.describe ChainPlan, type: :model do
      it 'does not allow an end_time which is after the start_time' do
        cp = described_class.new(
          start_time: Time.current,
          end_time: Time.current - 1.minute
        )
        cp.valid?
        expect(cp.errors.messages_for(:end_time)).to include 'must be after the start date'
      end
      it "allows a valid start_time/end_time combo" do
        cp = described_class.new(
          start_time: Time.current,
          end_time: Time.current.advance(10.minutes)
        )
        cp.valid?
        expect(cp.errors).to_not have_key :end_date
      end
    end
    

    而是设置对象,然后在其上调用valid? 以触发验证。在错误对象上写下期望以测试实际行为而不是地毯式轰炸。例如,在这里您会完全错过将错误添加到键 :end_date 而不是 :end_time 的位置。

    验证本身也可以改进:

    class ChainPlan < ApplicationRecord
      belongs_to :faction
      has_many :chain_plan_slots
      validates :start_time, presence: { on: :create, message: "can't be blank" }
      validates :end_time, presence: { on: :create, message: "can't be blank" }
      validates :faction, presence: { on: :create, message: "can't be blank" }
      validate :end_date_after_start_date?, if: ->{ end_time.present? && start_time.present? }
    
      private
    
      def end_date_after_start_date?
        errors.add(:end_time, 'must be after the start date') if end_time < start_time
      end
    end
    

    【讨论】:

    • errors.messages_for(:end_time) 可以替换为来自 rspec-rails relishapp.com/rspec/rspec-rails/v/2-14/docs/model-specs/…errors_on
    • @NikitaFedyashev 对于当前版本的 rspec-rails,它们是否仍然存在?这些文档适用于旧版本。
    • 是的 errors_on 仍然存在于 rspec-rails 中(从 ~ 2.12.1 开始)并且 API 没有改变。
    【解决方案2】:

    我认为问题出在Date.now,这不是一个正确的命令——至少从documentation 我找不到Date 类的now 方法。请改用Time.now。这对我来说很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多