Factory-Girlは、モデルの検証をバイパスするものを作成します
-
27-10-2019 - |
質問
私は工場の女の子を使用して、グループのモデル/ユニットテストで2つのインスタンスを作成しています。モデルをテストして、.currentへの呼び出しが、次のように有効期限属性に従って「現在」グループのみを返すことを確認しています...
describe ".current" do
let!(:current_group) { FactoryGirl.create(:group, :expiry => Time.now + 1.week) }
let!(:expired_group) { FactoryGirl.create(:group, :expiry => Time.now - 3.days) }
specify { Group.current.should == [current_group] }
end
私の問題は、新しいグループの有効期限をチェックすることが今日の日付以降であることをモデルに検証していることです。これにより、以下の検証障害が発生します。
1) Group.current
Failure/Error: let!(:expired_group) { FactoryGirl.create(:group, :expiry => Time.now - 3.days) }
ActiveRecord::RecordInvalid:
Validation failed: Expiry is before todays date
工場の女の子を使用して作成するときに、グループを強制的に作成したり、検証を回避する方法はありますか?
解決
これはFactoryGirlにあまり固有ではありませんが、モデルを介して保存するときはいつでも検証をバイパスできます save(:validate => false)
:
describe ".current" do
let!(:current_group) { FactoryGirl.create(:group) }
let!(:old_group) {
g = FactoryGirl.build(:group, :expiry => Time.now - 3.days)
g.save(:validate => false)
g
}
specify { Group.current.should == [current_group] }
end
他のヒント
このソリューションが好きです https://github.com/thoughtbot/factory_girl/issues/578.
工場内:
to_create {|instance| instance.save(validate: false) }
編集:
参照されたスレッドで述べたように、および他のコメント/ソリューションによって、テストの他の場所での混乱/問題を避けるために、これを特性ブロックに包むことをお勧めします。たとえば、検証をテストするとき。
工場でデフォルトで検証をスキップするのは悪い考えです。それを見つけて、いくつかの髪が引き出されます。
最も素晴らしい方法だと思います:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
次に、テストで:
create(:group, :skip_validate, expiry: Time.now + 1.week)
この特定のDATE-BAESD検証ケースでは、 タイムコップ 宝石時間を一時的に変更して、過去に作成されている古いレコードをシミュレートします。
foo = build(:foo).tap{ |u| u.save(validate: false) }
工場はデフォルトで有効なオブジェクトを作成する必要があります。見つけた 一時的な属性 次のような条件付きロジックを追加するために使用できます。
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
テストで:
create(:group, skip_validations: true)
そのモデルのすべての検証をスキップすることは最善ではありません。
作成 spec/factories/traits.rb
ファイル。
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
仕様を修正します
describe ".current" do
let!(:current_group) { FactoryGirl.create(:group, :skip_validate, :expiry => Time.now + 1.week) }
let!(:expired_group) { FactoryGirl.create(:group, :skip_validate, :expiry => Time.now - 3.days) }
specify { Group.current.should == [current_group] }
end
シナリオに応じて、更新でのみ検証を変更することができます。例: :validates :expire_date, :presence => true, :on => [:update ]