Rspec 积分工厂测试中
Rspec integral factories in test
如果我的英语不完美,我深表歉意,但这不是我的母语。
我必须使用 Rails 4.2、Rspec 3.3 和 FactoryGirl 4.5 测试 MySql 数据库。
基本模型的测试是绿色的。当我必须测试包含无法复制的外键的模型时,问题就来了。
起初我有两个模型(dimension.rb 到 feature.rb 和 technical.rb) 每个都有一个来自同一模型的外键 (current.rb):
#models/dimension.rb
class Dimension < ActiveRecord::Base
belongs_to :current
has_many :features
...
end
#models/feature.rb
class Feature < ActiveRecord::Base
belongs_to :dimension
has_many :bxes
...
end
#models/technical.rb
class Technical < ActiveRecord::Base
belongs_to :current
has_many :bxes
...
end
这两个模型放在最终模型中(bxe.rb)
#models/bxe.rb
class Bxe < ActiveRecord::Base
belongs_to :feature
belongs_to :technical
...
validates :technical_id, presence: true
validates :feature_id, presence: true
end
当前型号为:
#models/current.rb
class Current < ActiveRecord::Base
has_many :technicals
has_many :dimensions
validates :current, presence: true, uniqueness: true
validates :value, presence: true, uniqueness: true
end
工厂如下:
#spec/factories/current.rb
FactoryGirl.define do
factory :current do
trait :lower do
current '800A'
value 800
end
trait :higher do
current '2000A'
value 2000
end
end
end
#spec/factories/dimension.rb
FactoryGirl.define do
factory :dimension do
...
trait :one do
current {create(:current, :lower)}
end
trait :two do
current {create(:current, :higher)}
end
end
end
#spec/factories/feature.rb
FactoryGirl.define do
factory :feature do
descr 'MyString'
dimension { create(:dimension, :one) }
...
end
end
#spec/factories/technical.rb
FactoryGirl.define do
factory :technical do
...
trait :A do
current { create(:current, :lower) }
end
trait :L do
current { create(:current, :higher) }
end
end
end
#spec/factories/bxes.rb
FactoryGirl.define do
factory :bxe do
...
technical {create(:technical, :A) }
feature
end
end
当我 运行 在模型上测试第一个命令 (technical) 运行s 并且工厂创建一个 ID = 1 的当前记录但是第二个 (features) 失败了,因为工厂再次尝试使用相同的数据创建 Current 的记录,模型 current.rb[ 禁止的操作=41=]
#rspec spec/models
2.1.2 :001 > FactoryGirl.create(:bxebusbar, :one)
... Current Exists ... SELECT 1 AS one FROM `currents` WHERE `currents`.`current` = BINARY '800A' LIMIT 1
... INSERT INTO `currents` (`current`, `value`, `created_at`, `updated_at`) VALUES ('800A', 800, ..., ...)
... INSERT INTO `technicals` (..., `current_id`, ..., `created_at`, `updated_at`) VALUES (..., 1, ..., ...)
... Current Exists ... SELECT 1 AS one FROM `currents` WHERE `currents`.`current` = BINARY '800A' LIMIT 1
... ActiveRecord::RecordInvalid: Validation failed: Current has already been taken, Value has already been taken
我认为可以通过仅创建一次当前记录然后在 technical 和 features 工厂中使用它来解决问题,现实中会发生什么,但我不知道该怎么做。
有什么建议吗?谢谢
您可以使用sequences生成不会重复的值。另一种选择是使用 DatabaseCleaner 并将其设置为在每次测试后清理数据库。
第一个选项:
FactoryGirl.define do
factory :current do
trait :lower do
sequence :current do { |n| "#{n}A" }
sequence :value do {|n| "#{n}" }
end
end
end
或设置数据库清理器:Database cleaner
如果我的英语不完美,我深表歉意,但这不是我的母语。
我必须使用 Rails 4.2、Rspec 3.3 和 FactoryGirl 4.5 测试 MySql 数据库。
基本模型的测试是绿色的。当我必须测试包含无法复制的外键的模型时,问题就来了。
起初我有两个模型(dimension.rb 到 feature.rb 和 technical.rb) 每个都有一个来自同一模型的外键 (current.rb):
#models/dimension.rb
class Dimension < ActiveRecord::Base
belongs_to :current
has_many :features
...
end
#models/feature.rb
class Feature < ActiveRecord::Base
belongs_to :dimension
has_many :bxes
...
end
#models/technical.rb
class Technical < ActiveRecord::Base
belongs_to :current
has_many :bxes
...
end
这两个模型放在最终模型中(bxe.rb)
#models/bxe.rb
class Bxe < ActiveRecord::Base
belongs_to :feature
belongs_to :technical
...
validates :technical_id, presence: true
validates :feature_id, presence: true
end
当前型号为:
#models/current.rb
class Current < ActiveRecord::Base
has_many :technicals
has_many :dimensions
validates :current, presence: true, uniqueness: true
validates :value, presence: true, uniqueness: true
end
工厂如下:
#spec/factories/current.rb
FactoryGirl.define do
factory :current do
trait :lower do
current '800A'
value 800
end
trait :higher do
current '2000A'
value 2000
end
end
end
#spec/factories/dimension.rb
FactoryGirl.define do
factory :dimension do
...
trait :one do
current {create(:current, :lower)}
end
trait :two do
current {create(:current, :higher)}
end
end
end
#spec/factories/feature.rb
FactoryGirl.define do
factory :feature do
descr 'MyString'
dimension { create(:dimension, :one) }
...
end
end
#spec/factories/technical.rb
FactoryGirl.define do
factory :technical do
...
trait :A do
current { create(:current, :lower) }
end
trait :L do
current { create(:current, :higher) }
end
end
end
#spec/factories/bxes.rb
FactoryGirl.define do
factory :bxe do
...
technical {create(:technical, :A) }
feature
end
end
当我 运行 在模型上测试第一个命令 (technical) 运行s 并且工厂创建一个 ID = 1 的当前记录但是第二个 (features) 失败了,因为工厂再次尝试使用相同的数据创建 Current 的记录,模型 current.rb[ 禁止的操作=41=]
#rspec spec/models
2.1.2 :001 > FactoryGirl.create(:bxebusbar, :one)
... Current Exists ... SELECT 1 AS one FROM `currents` WHERE `currents`.`current` = BINARY '800A' LIMIT 1
... INSERT INTO `currents` (`current`, `value`, `created_at`, `updated_at`) VALUES ('800A', 800, ..., ...)
... INSERT INTO `technicals` (..., `current_id`, ..., `created_at`, `updated_at`) VALUES (..., 1, ..., ...)
... Current Exists ... SELECT 1 AS one FROM `currents` WHERE `currents`.`current` = BINARY '800A' LIMIT 1
... ActiveRecord::RecordInvalid: Validation failed: Current has already been taken, Value has already been taken
我认为可以通过仅创建一次当前记录然后在 technical 和 features 工厂中使用它来解决问题,现实中会发生什么,但我不知道该怎么做。 有什么建议吗?谢谢
您可以使用sequences生成不会重复的值。另一种选择是使用 DatabaseCleaner 并将其设置为在每次测试后清理数据库。
第一个选项:
FactoryGirl.define do
factory :current do
trait :lower do
sequence :current do { |n| "#{n}A" }
sequence :value do {|n| "#{n}" }
end
end
end
或设置数据库清理器:Database cleaner