【问题标题】:Rails uniqueness validation test failingRails 唯一性验证测试失败
【发布时间】:2015-03-15 08:38:22
【问题描述】:

我从 Rails 4.2 开始,我正在尝试测试我正在制作的 Item 模型的唯一性,我运行了以下代码:

item.rb:

class Item < ActiveRecord::Base
    attr_accessor :name
    validates :name, uniqueness: true #, other validations...
end

item_test.rb:

require 'test_helper'

class ItemTest < ActiveSupport::TestCase

    def setup
        @item = Item.new(name: "Example Item")
    end

    test "name should be unique" do
        duplicate_item = @item.dup
        @item.save
        assert_not duplicate_item.valid?
    end
end

但测试没有通过,说assert_not 行出来了true,而它应该是nilfalse。我基本上从教程中得到了这段代码,但无法弄清楚为什么它没有通过。有什么帮助吗?

编辑:我找到了解决方案,通过不定义我在 setup 操作中定义的 @item 的其他成员(特别是 :price ),测试通过了。但是现在我不知道如何让它通过:price 成员。下面是 item.rb 和 item_test.rb 的完整实现。

item.rb:

class Item < ActiveRecord::Base
    attr_accessor :name, :description, :price
    validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
    validates :description, presence: true,
        length: { maximum: 1000 }
    VALID_PRICE_REGEX = /\A\d+(?:\.\d{0,2})?\z/
    validates :price, presence: true,
        :format => { with: VALID_PRICE_REGEX },
        :numericality => {:greater_than => 0}
end 

item_test.rb:

require 'test_helper'

class ItemTest < ActiveSupport::TestCase

    def setup
        @item = Item.new(name: "Example Item", description: "Some kind of item.", price: 1.00)
    end

    test "name should be unique" do
        duplicate_item = @item.dup
        @item.save
        assert_not duplicate_item.valid?
    end
end

【问题讨论】:

    标签: ruby-on-rails validation testing unique


    【解决方案1】:

    Almaron 的上述答案是正确的,应该是公认的答案。

    我正在添加这个答案来详细说明它。

    测试如下:

    require 'test_helper'
    
    class ItemTest < ActiveSupport::TestCase
    
      def setup
        @item = Item.create(name: "Example Item")
      end
    
      test "name should be unique" do
        duplicate_item = @item.dup
        assert_not duplicate_item.valid?
      end
    end
    

    注意:duplicate_item 在验证之前不需要保存。

    【讨论】:

    • 这两个答案都没有做出任何改变,尽管当我摆脱了该对象的所有其他成员时,它起作用了。现在的问题是我不确定如何验证它并保留其他成员。为了清楚起见,我更新了问题。
    【解决方案2】:

    对数据库中已经存在的记录执行唯一性验证。并且您的 Item.new(name: "Example Item") 在保存之前不在数据库中。因此,如果您改用Item.create(name: "Example Item"),则测试应该通过。

    【讨论】:

    • 这并没有做任何改变,尽管当我摆脱了对象的所有其他成员时它起作用了。现在的问题是我不确定如何验证它并保留其他成员。为了清楚起见,我更新了问题。
    【解决方案3】:

    您在编辑中至少发现了一些问题。

    问题不在于您使用Item.new 而不是Item.create,问题在于当您使用@item.save 时,@item 记录没有被保存,因为它存在其他验证问题。

    你可以试试……

    @item.save(validate: false)
    

    ...这将强制将@item 写入数据库,但测试并不能真正确定为什么duplicate_item 记录无效。

    最好测试一下您是否有与name 相关的错误...

    require 'test_helper'
    
    class ItemTest < ActiveSupport::TestCase
    
      def setup
        @item = Item.new(name: "Example Item")
      end
    
      test "name should be unique" do
        duplicate_item = @item.dup
        @item.save(validate: false)
        duplicate_item.valid? # need this to populate errors
        assert duplicate_item.errors
        assert duplicate_item.errors[:name]
      end
    end
    

    【讨论】:

    • 你在做某事,你的两个断言返回为真,但是当我使用 Rails::logger.debug 并检查 assert duplicate_item.errors.full_messages 的测试日志时,它返回为一个空数组
    • 你在断言之前做了duplicate_item.valid??在您测试有效性之前,它不会出错。
    【解决方案4】:

    我修复了它,我去掉了attr_accessor 行,然后测试能够访问属性并能够检测到重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      相关资源
      最近更新 更多