错误消息:
Failure/Error: let(:rubric_in_grenoble){ create(:rubric_in_grenoble) }
ActiveRecord::RecordInvalid:
Validation failed: Name has already been taken
所以,正如我想的那样:第二次尝试创建:rubric工厂 时间(因为:rubric_in_grenoble应该与之关联 相同的文化:rubric_in_wroclaw)。我应该如何更改此代码 不要再次创建相同的工厂模型,而是将其与 现有的? 我使用Database Cleaner
我正在为模型人口编写测试。
class Population < ApplicationRecord
belongs_to :province
belongs_to :culture
validates_presence_of :province, :culture
#some methods
end
与省相关联
class Province < ApplicationRecord
enum terrain: [:sea, :plains, :hills, :mountains]
validates :terrain, presence: true
validates :name,
presence: true,
uniqueness: true,
format: {
with: /\A[A-Za-z ]{3,30}\z/,
message: "province name has to contain letters and spaces only"
}
has_many :populations
##some methods
end
和文化
class Culture < ApplicationRecord
before_validation :downcase_name
validates :name, presence: true,
format: {
with: /\A[a-z]{3,20}\z/,
message: "culture name has to contain letters only"
},
length: { minimum: 3, maximum: 20 }
##many-to-many associations to different model - tested correctly
has_many :populations
end
在我的测试套件中,我使用FactoryGirl和RSpec。 Rails 5.0.1。我也安装了simplecov(我99.99%确定它没有干扰,但最好强调这一点)并且DatabaseCleaner正常工作。
文化和省级模型经过测试,一切都很好。在我的FactoryGirl文件中,人口有:
FactoryGirl.define do
factory :rubric_in_wroclaw, class: "Population" do
association :province, factory: :wroclaw
association :culture, factory: :rubric
quantity 10
end
factory :javan_in_wroclaw, class: 'Population' do
association :province, factory: :grenoble
association :culture, factory: :javan
quantity 15
end
factory :rubric_in_grenoble, class: 'Population' do
association :province, factory: :grenoble
association :culture, factory: :rubric
quantity 25
end
end
在我的population_spec.rb文件中,我得到了:
require 'rails_helper'
RSpec.describe Population, type: :model do
let(:rubric_in_wroclaw){ create(:rubric_in_wroclaw) }
let(:javan_in_wroclaw){ create(:javan_in_wroclaw) }
let(:rubric_in_grenoble){ create(:rubric_in_grenoble) }
let(:pops){ [ rubric_in_wroclaw, javan_in_wroclaw, rubric_in_grenoble] }
describe '#validations' #shoulda-matchers validations - GREEN
describe '#methods' do
describe '#global_population' do
context 'without any pop' #without any fixture created
context 'with many pops' do
before { pops } <--- there is an error
it 'is equal to 50' do
expect(Population.global_population).to eq 50
end
end
end**
end
describe '#factories' #each factory is tested separately - everything's ok
end
重复的问题(因为帖子很长)
所以,正如我想的那样:第二次尝试创建:rubric工厂 时间(因为:rubric_in_grenoble应该与之关联 相同的文化:rubric_in_wroclaw)。我应该如何更改此代码 不要再次创建相同的工厂模型,而是将其与 现有的?
答案 0 :(得分:0)
简答:
您可能正在为Province.name
字段提供重复值。 sequence应解决问题。
长答案:
让我们再看看错误。
Failure/Error: let(:rubric_in_grenoble){ create(:rubric_in_grenoble) }
ActiveRecord::RecordInvalid:
Validation failed: Name has already been taken
异常告诉我们,我们正在尝试创建一个名称两次的记录
我可以在uniqueness
中看到Province.name
验证。
class Province < ApplicationRecord
enum terrain: [:sea, :plains, :hills, :mountains]
validates :terrain, presence: true
validates :name,
presence: true,
uniqueness: true,
format: {
with: /\A[A-Za-z ]{3,30}\z/,
message: "province name has to contain letters and spaces only"
}
has_many :populations
##some methods
end
你没有粘贴Province
工厂,但我希望工厂是这样的:
FactoryGirl.define do
factory :my_factory, class: "Province" do
name 'blabla'
# other fields
end
end
所以我们必须使用序列而不是静态值。
FactoryGirl.define do
factory :grenoble, class: "Province" do
sequence(:name) { |i| "BLABLA#{(i+64).chr}" }
# other fields
end
end
RSpec.describe Population, type: :model do
let(:my_province){ create(:my_province) }
let(:rubric_in_wroclaw){ create(:rubric_in_wroclaw, province: :my_province) }
let(:javan_in_wroclaw){ create(:javan_in_wroclaw, province: :my_province) }
end