Rspec 如何使用Shoulda正确检查唯一性和范围
我有一个Rspec 如何使用Shoulda正确检查唯一性和范围,rspec,shoulda,Rspec,Shoulda,我有一个用户模型,它具有项的子关联。项目的:name对于用户来说应该是唯一的,但是它应该允许不同的用户拥有相同名称的项目 项目模型当前设置为: class Item < ApplicationRecord belongs_to :user validates :name, case_sensitive: false, uniqueness: { scope: :user } end 但该测试失败是因为: Failure/Error: it { should validate_un
用户
模型,它具有项的子关联
。项目的:name
对于用户来说应该是唯一的,但是它应该允许不同的用户拥有相同名称的项目
项目模型当前设置为:
class Item < ApplicationRecord
belongs_to :user
validates :name, case_sensitive: false, uniqueness: { scope: :user }
end
但该测试失败是因为:
Failure/Error: it { should validate_uniqueness_of(:name).scoped_to(:user).case_insensitive }
Item did not properly validate that :name is case-insensitively
unique within the scope of :user.
After taking the given Item, setting its :name to ‹"an
arbitrary value"›, and saving it as the existing record, then making a
new Item and setting its :name to a different value, ‹"AN
ARBITRARY VALUE"› and its :user to a different value, ‹nil›, the
matcher expected the new Item to be invalid, but it was valid
instead.
然而,这就是我想要的行为(除了应该为用户选择nil
的奇怪部分)。当用户不同时,相同的名称应有效
有可能我没有正确使用范围测试,或者这在Shoulda中是不可能的。在这种情况下,您将如何编写模型测试来测试此行为?解决方案有三个方面:
:user\u id
,而不是模型中的:user
:用户id
我用
enum
模型
试验
但总是得到类型错误(即enum
值在测试中大写)
但我能够编写一个通过的显式测试
it 'validates uniqueness of plan_type scoped to benefit_class_id' do
rp1 = FactoryBot.create(:retirement_plan)
rp2 = FactoryBot.build(
:retirement_plan,
benefit_class_id: rp1.benefit_class_id,
plan_type: rp1.plan_type,
)
expect(rp2).to_not be_valid
end
唯一性匹配器不支持将关联用作作用域,有。作为一种解决方法,您应该使用
scoped\u to(:user\u id)
。但即使有了这一变化,scope\u to
和case\u insensitive
似乎也不起作用。我认为这是一个错误@一个正常工作的耳机你能报告吗?否则我会做的。@ana06很好,谢谢!我将打开一个新问题,并引用您链接的问题。此处打开的问题:此问题现在似乎已解决。您的第二个测试与shoulda测试的条件不同。如果不区分大小写,shoulda测试将同时查看rpp
和rpp
。您的测试不检查第二种情况,它只是将其设置为相同的值。
class Item < ApplicationRecord
belongs_to :user
validates :name, uniqueness: { scope: :user_id, case_sensitive: false }
end
RSpec.describe Item, type: :model do
describe 'validations' do
it { should validate_uniqueness_of(:name).scoped_to(:user_id).case_insensitive }
end
end
validates(:plan_type,
uniqueness: { scope: :benefit_class_id, case_sensitive: false })
enum plan_type: {
rrsp: 0,
dpsp: 1,
tfsa: 2,
nrsp: 3,
rpp: 4,
}
it { should validate_uniqueness_of(:plan_type).scoped_to(:benefit_class_id).case_insensitive }
1) BenefitClass::RetirementPlan validations should validate that :plan_type is case-insensitively unique within the scope of :benefit_class_id
Failure/Error:
is_expected.to validate_uniqueness_of(:plan_type)
.scoped_to(:benefit_class_id).case_insensitive
ArgumentError:
'RPP' is not a valid plan_type
it 'validates uniqueness of plan_type scoped to benefit_class_id' do
rp1 = FactoryBot.create(:retirement_plan)
rp2 = FactoryBot.build(
:retirement_plan,
benefit_class_id: rp1.benefit_class_id,
plan_type: rp1.plan_type,
)
expect(rp2).to_not be_valid
end