【问题标题】:Custom validator on associated model make other Rspec model tests break关联模型上的自定义验证器使其他 Rspec 模型测试中断
【发布时间】:2017-10-11 13:39:25
【问题描述】:

我有 2 个模型共享一个简单的 belongs_to/has_many 关系:房间属于建筑

我创建了一个名为 total_number_rooms_limited_to_15 的自定义验证器,以确保我不能为给定的建筑物创建超过 15 个房间。

class Room < ActiveRecord::Base

    # -- Relationships --------------------------------------------------------
  belongs_to :admin_user,     :foreign_key => 'admin_user_id'
  belongs_to :building,        :foreign_key => 'building_id'

  # -- Validations ----------------------------------------------------------              

  validates :room_filename,
              presence: true             

  # associated models primary key validates 
  validates :admin_user_id,
     presence: true
  validates :building_id,
     presence: true  

  validate :total_number_rooms_limited_to_15

  private

    def total_number_rooms_limited_to_15
      errors[:base] <<  "There can't be more than 15 rooms. There are already 15 .
                        <br/>Please remove another one or drop trying adding this one.".html_safe 
          unless ( self.building.rooms.count < 15 )
    end

但问题是,在创建了这个新的验证器之后,我所有的“常规”基本测试都失败了。

require 'spec_helper'

RSpec.describe Room, type: :model do

  before(:each) do
    @attr = {
      room_filename:                               "xyz" 
    }
  end  

  # -- Models Tests --------------------------------------------------------
  describe "tests on ST's models validations for room_filename" do
    it { is_expected.to validate_presence_of(:room_filename) }    
    it { is_expected.not_to allow_value(" ").for(:room_filename) }    
  end

都给我以下错误信息:

1) Room tests on ST's models validations for room_filename should validate that :room_filename cannot be empty/falsy
     Failure/Error:
       errors[:base] <<  "There can't be more than 15 rooms. There are already 15 .
                         <br/>Please remove another one or drop trying adding this one.".html_safe unless ( self.building.rooms.count < 15 )

     NoMethodError:
       undefined method `rooms' for nil:NilClass

我尝试在 @attr 属性中添加关联的“虚拟”建筑,但没有成功;得到相同的错误消息:

before(:each) do
    @attr = {
      room_filename:                               "xyz",
      building_id:                                 1
    }

添加信息

config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation, :except => %w(roles)) 
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

【问题讨论】:

  • 您是否在每次运行测试之前删除数据库中的所有内容?
  • 看起来self.rooms.count self 为零? self 是什么?
  • @kris:我很久以前就设置了,但我认为是的。我现在将从我的 spec_helper 中添加一个可能有用的要点
  • 这个方法在我的文件 models/room.rb 中,所以 self 是一个房间。我的方法使用 self.building.rooms.count => 所以 self 是当前房间然后 self.building 去寻找房间所属的建筑物和 self.building.rooms.count 去计算后者的所有房间。
  • 您的错误中提到了self.rooms.count &lt; 15,而您的示例代码中提到了self.building.rooms.count &lt; 15。哪个是正确的?

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


【解决方案1】:

对于自定义验证,您需要在测试中实例化一个新的 Room 对象。如果您没有像 factory_girlfabrication 这样的东西来为您的测试创建对象,您可以这样做:

before(:each) do
  @admin_user = AdminUser.create!(...attributes)
  @building = Building.create!(...attributes)
  @room = Room.create!(building_id: @building.id, admin_user_id: @admin_user.id)
end

然后确保您在实例而不是 Room 类上调用验证:

def total_number_rooms_limited_to_15
  errors[:base] <<  "There can't be more...".html_safe 
  unless ( building.present? && building.rooms.count < 15 )
end

【讨论】:

  • 谢谢。我正在使用 Factory_girl(不在此精确测试中,但我可以使用它)。明天试试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
  • 2012-12-25
  • 2019-10-02
  • 1970-01-01
相关资源
最近更新 更多