Rspec'validates_numericality_o'f测试失败,并使用FactoryBot和奇怪的错误

问题描述 投票:0回答:1

我正在尝试在我们公司的Rails应用中实施更多测试,并使用Rspec,FactoryBot和Shoulda匹配器来提供帮助。这些基础很容易实现,例如关联和presentation_of。鉴于FactoryBot产生了良好的测试实例,在那些比较“奇特”的错误中,我遇到了麻烦并遇到了一些我不太了解如何解决的错误。这是我正在测试的模型:

class Outage < ApplicationRecord
    belongs_to :service 

    validates_presence_of :start_time, :end_time, :reason, :frequency
    validates_numericality_of :start_time 
    validates_numericality_of :end_time, :is_greater_than => :start_time 
end

这里是FactoryBot文件:

FactoryBot.define do 
   factory :outage_fo, class: 'Outage' do 
        start_time { Time.now }
        end_time { Time.now + Random.rand(1e5..1e6).floor}
        is_recurring { false }
        frequency { "None" }
        reason { Faker::Company.bs }
        service_id { Random.rand(1..50) }
   end 

   factory :outage_ro, class: 'Outage' do 
        start_time { Time.now }
        end_time { Time.now + Random.rand(1e5..1e6).floor}
        is_recurring { true }
        frequency { ["Daily", "Monthly" ].sample }
        reason { Faker::Company.bs }
        service_id { Random.rand(1..50) }
   end 
end

这是实际的RSpec测试:


require 'rails_helper'

RSpec.describe Outage, type: :model do
  let(:outage_fo) { build(:outage_fo) }


  describe "associations" do 
    it { should belong_to(:service) }
  end

  describe "validations" do 
    it { should validate_presence_of(:start_time) }
    it { should validate_presence_of(:end_time) }
    it { should validate_presence_of(:reason) }
    it { should validate_presence_of(:frequency) }
    it { should validate_numericality_of(:end_time).is_greater_than(Time.now) }
  end


end

我得到的错误是:


  1) Outage validations is expected to validate that :end_time looks like a number greater than 2020-04-20 12:57:33 -0400
     Failure/Error: it { should validate_numericality_of(:end_time).is_greater_than(Time.now) }

       Expected Outage to validate that :end_time looks like a number greater
       than 2020-04-20 12:57:33 -0400, but this could not be proved.
         After setting :end_time to ‹"2020-04-20 12:57:33 -0400"› -- which was
         read back as ‹Mon, 20 Apr 2020 16:57:33 UTC +00:00› -- the matcher
         expected the Outage to be invalid and to produce the validation error
         "must be greater than 2020-04-20 12:57:33 -0400" on :end_time. The
         record was indeed invalid, but it produced these validation errors
         instead:

         * service: ["must exist"]
         * start_time: ["can't be blank"]
         * reason: ["can't be blank"]
         * end_time: ["is not a number"]

         As indicated in the message above, :end_time seems to be changing
         certain values as they are set, and this could have something to do
         with why this test is failing. If you've overridden the writer method
         for this attribute, then you may need to change it to make this test
         pass, or do something else entirely.
     # ./spec/models/outage_spec.rb:16:in `block (3 levels) in <top (required)>'

Finished in 0.24732 seconds (files took 1.87 seconds to load)
6 examples, 1 failure

Failed examples:

rspec ./spec/models/outage_spec.rb:16 # Outage validations is expected to validate that :end_time looks like a number greater than 2020-04-20 12:57:33 -0400

[12:57:33] (develop_2) tml_dashboard_2
// ♥ rspec spec/models/outage_spec.rb
.....F

Failures:

  1) Outage validations is expected to validate that :end_time looks like a number greater than 2020-04-20 12:58:31 -0400
     Failure/Error: it { should validate_numericality_of(:end_time).is_greater_than(Time.now) }

       Expected Outage to validate that :end_time looks like a number greater
       than 2020-04-20 12:58:31 -0400, but this could not be proved.
         After setting :end_time to ‹"2020-04-20 12:58:31 -0400"› -- which was
         read back as ‹Mon, 20 Apr 2020 16:58:31 UTC +00:00› -- the matcher
         expected the Outage to be invalid and to produce the validation error
         "must be greater than 2020-04-20 12:58:31 -0400" on :end_time. The
         record was indeed invalid, but it produced these validation errors
         instead:

         * service: ["must exist"]
         * start_time: ["can't be blank", "is not a number"]
         * reason: ["can't be blank"]
         * end_time: ["is not a number"]

         As indicated in the message above, :end_time seems to be changing
         certain values as they are set, and this could have something to do
         with why this test is failing. If you've overridden the writer method
         for this attribute, then you may need to change it to make this test
         pass, or do something else entirely.
     # ./spec/models/outage_spec.rb:16:in `block (3 levels) in <top (required)>'

Finished in 0.23808 seconds (files took 1.77 seconds to load)
6 examples, 1 failure
ruby-on-rails testing rspec factory-bot
1个回答
0
投票

validates_numericality不适用于日期/日期时间属性。有单独的宝石,例如validates_timelines,可以实现日期验证,也可以编写自己的自定义验证。

class Outage
  validate :end_time_is_after_start

  private
  def end_time_is_after_start
    errors.add(:end_time, 'is not after start time') unless end_time > start_time
  end
end

处理工厂时间的更好方法是使用相关属性:

factory :outage_fo, class: 'Outage' do 
  start_time { Time.now }
  end_time { start_time + rand(5..100).minutes }
  is_recurring { false }
  frequency { "None" }
  reason { Faker::Company.bs }
  service_id { Random.rand(1..50) }
end 

这可以确保end_time总是相对于start_time。

© www.soinside.com 2019 - 2024. All rights reserved.