【问题标题】:Rspec integral factories in test测试中的 Rspec 积分工厂
【发布时间】:2015-08-03 20:49:18
【问题描述】:

如果我的英语不完美但不是我的母语,我深表歉意。
我必须使用 Rails 4.2、Rspec 3.3 和 FactoryGirl 4.5 测试 MySql 数据库。
基本模型的测试是绿色的。当我必须测试包含无法复制的外键的模型时,问题就出现了。
起初我有两个模型(dimension.rbfeature.rbtechnical.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) 运行,工厂创建了一个 id = 1 的当前记录,但第二个命令 (features) 失败, 由于工厂再次尝试创建具有相同数据的 Current 记录,因此模型禁止操作 current.rb

#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

我认为可以通过只创建一次当前记录然后在 technicalfeatures 工厂中使用它来解决问题,实际会发生什么,但我不知道该怎么做。 有什么建议吗?谢谢

【问题讨论】:

    标签: ruby ruby-on-rails-4 rspec factory-bot ruby-on-rails-4.2


    【解决方案1】:

    您可以使用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

    【讨论】:

    • 感谢您的建议。这样就解决了测试的问题。但是,我不会有两个不同的当前记录。事实上,对象 BXE 来自两个绑定到同一个外键 (current) 的表。如果这不可能,我想我会修改数据库关系
    • 然后只需使用 Database Cleaner 并围绕每个测试套件配置清理。然后每次输入新测试时都会重新创建对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多