我有一个
ActiveRecord
表,其中有一列名为 name
。我需要这个字段存在并且是唯一的。所以我有以下规格
it { should validate_presence_of(:name) }
it { should validate_uniqueness_of(:name) }
模型中对应的规则为:
validates :name, presence: true, uniqueness: true
我的工厂包含以下内容:
FactoryBot.define do
factory :model_name do
sequence(:name) { |n| "Name #{n}" }
after(:build) do |model|
pack.rels << build(:relation)
end
end
end
问题是,当我运行规范时,出现以下错误。
Failure/Error: it { should validate_uniqueness_of(:name) }
Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher::ExistingRecordInvalid:
validate_uniqueness_of works by matching a new record against an
existing record. If there is no existing record, it will create one
Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `table_name`
我做错了什么?
validate_uniqueness_of
匹配器与其他匹配相比,其行为有所不同,因为如果模型尚不存在,它会为模型创建一个实例。 文档中有一个警告部分,详细介绍了您的问题中描述的场景。
为了解决这个问题,您需要在测试范围内创建一个具有预填充字段的对象,以便您可以控制执行期间使用的属性值。
由于您使用的是 FactoryBot,您可以执行以下操作:
RSpec.describe ModelName, type: :model do
describe "validations" do
subject { FactoryBot.build(:model_name) }
it { should validate_presence_of(:name) }
it { should validate_uniqueness_of(:name) }
end
end