【问题标题】:Rspec model tests failing due to custom validation method not being found由于未找到自定义验证方法,Rspec 模型测试失败
【发布时间】:2021-01-28 15:53:36
【问题描述】:

由于某种原因,我的一个模型的 Rspec 模型测试失败,原因是正在调用自定义验证方法,但在测试中找不到。至少这是我认为正在发生的事情。当提交表单以在应用程序中创建新恐龙时触发此验证。谁能告诉我为什么会发生这种情况以及可能的解决方法是什么?

这是所有 4 个测试的失败错误:

Failure/Error: if cage.at_capacity?
     
     NoMethodError:
       undefined method `at_capacity?' for nil:NilClass

模型/dinosaur.rb

class Dinosaur < ApplicationRecord
    belongs_to :cage
    validates :name, :species, :diet_type, :cage_id, presence: true
    validates_uniqueness_of :name
    validate :is_cage_at_capacity
    validate :is_cage_powered_down
    validate :cage_contains_diet_mismatch

=begin
    def set_cage(c)

        return false if c.at_capacity?
        cage = c

    end

    def move_dino_to_powered_down_cage(c)

        return false if c.is_powered_down?
        cage = c

    end
=end

    def is_herbivore?
        return diet_type == "Herbivore"
    end

    def is_carnivore?
        return diet_type == "Carnivore"
    end

    def is_cage_powered_down
        if cage.is_powered_down?
            errors.add(:cage_id, "Chosen cage is powered down. Please choose another cage!")
        end
    end

    def is_cage_at_capacity
        if cage.at_capacity?
            errors.add(:cage_id, "Chosen cage is full. Please choose another cage!")
            end
    end

    def cage_contains_diet_mismatch
        if cage.has_carnivore == true and is_herbivore?
            errors.add(:cage_id, "Chosen cage contains carnivores! This dinosaur will be eaten!")
        else
            if cage.has_herbivore == true and is_carnivore?
                errors.add(:cage_id, "Chosen cage contains herbivores! This dinosaur will eat the others!")
            end
        end
    end


end

spec/models/dinosaur_spec.rb

require 'rails_helper'

describe Dinosaur, type: :model do

    it "is valid with valid attributes" do
        dinosaur = Dinosaur.new(name:"Yellow", species:"Tyrranosaurus", diet_type:"Carnivore", cage_id: 7)
        expect(dinosaur).to be_valid
    end

    it "is not valid without a name" do
        dinosaur = Dinosaur.new(name: nil)
        expect(dinosaur).to_not be_valid
    end
    it "is not valid without a max capacity" do
        dinosaur = Dinosaur.new(species: nil)
        expect(dinosaur).to_not be_valid
    end
    it "is not valid without a power status" do
        dinosaur = Dinosaur.new(diet_type: nil)
        expect(dinosaur).to_not be_valid
    end
end

【问题讨论】:

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


    【解决方案1】:

    为什么会这样?

    当您调用方法valid? 时,所有验证都会被触发。至少,is_cage_at_capacity 调用了dinosaur.cage.at_capacity?。但是,Dinosaur.new(diet_type: nil) 没有任何笼子,因此引发了异常。

    如何解决?

    最简单的方法是在测试中添加一个笼子:

    cage = Cage.new
    dinosaur = cage.build_dinosaur(params)
    

    每次都构建所有这些对象可能会非常重复,因此请考虑使用FactoryBot with associations

    在测试验证时,测试预期错误而不是整个对象状态会更精确。检查this

    对于内置验证(例如存在性、唯一性),最好使用shoulda-matchers

    【讨论】:

      【解决方案2】:

      貌似程序执行到is_cage_at_capacity方法cage没有设置,其实错误有线索:undefined method 'at_capacity?' for nil:NilClass这表示你正在尝试将at_capacity?方法发送到nil对象。

      所以,我认为修复它的一些选项是确保笼子在创建时与恐龙相关联,或者在 is_cage_at_capacity 方法中添加保护子句,如下所示:

      def is_cage_at_capacity
        if cage.nil?
          errors.add(:cage_id, "There is not a cage associated with the dinosaur")
        end
      
        if cage.at_capacity?
          errors.add(:cage_id, "Chosen cage is full. Please choose another cage!")
        end
      end
      

      【讨论】:

        猜你喜欢
        • 2015-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-05
        相关资源
        最近更新 更多