Rails 唯一性验证测试失败

Rails uniqueness validation test failing

我从 Rails 4.2 开始,我正在尝试测试我正在制作的项目模型的唯一性,我 运行 此代码:

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行在应该nil或者false的时候出来了true。我基本上是从教程中获得这段代码,但无法弄清楚为什么它没有通过。有帮助吗?

编辑:我找到了解决方案,方法是不定义我在 [=21] 中定义的 @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

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

上面阿尔马龙的回答是正确的,应该是公认的答案。

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

测试如下:

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验证前不需要保存。

您至少发现了您编辑中的部分问题。

问题不在于您使用 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

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