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
行,然后测试能够访问属性并能够检测到重复项。
我从 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
行,然后测试能够访问属性并能够检测到重复项。