web-dev-qa-db-ja.com

モデル検証をバイパスするファクトリーガールクリエイト

Factory Girlを使用して、グループのモデル/ユニットテストで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

Factory Girlを使用して作成するときに、グループを強制的に作成する方法や検証を回避する方法はありますか?

67
Norto23

これは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
82
Brandan

https://github.com/thoughtbot/factory_girl/issues/578 からこのソリューションを好みます。

工場内:

to_create {|instance| instance.save(validate: false) }

編集:

参照スレッドで述べられているように、また他のコメント/ソリューションで述べられているように、テストの他の場所での混乱/問題を避けるために、これを特性ブロックでラップすることになるでしょう。たとえば、検証をテストするとき。

50
Jason Denney

工場でデフォルトで検証をスキップするのは悪い考えです。それを見つけて、いくつかの髪が引き抜かれます。

最も良い方法は、私は思う:

trait :skip_validate do
  to_create {|instance| instance.save(validate: false)}
end

次に、テストで:

create(:group, :skip_validate, expiry: Time.now + 1.week)
22
Tim Scott

この特定の日付ベースの検証の場合、 timecop gemを使用して一時的に時間を変更し、過去に作成された古いレコードをシミュレートすることもできます。

7
foo = build(:foo).tap{ |u| u.save(validate: false) }
4
Chris Habgood

そのモデルのすべての検証をスキップすることは最善ではありません。

作成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
2
HAZI

シナリオに応じて、更新時にのみ検証を実行するように変更できます。例::validates :expire_date, :presence => true, :on => [:update ]

1
JoaoHornburg

工場ではデフォルトで有効なオブジェクトを作成する必要があります。 transient attributes を使用して、次のような条件付きロジックを追加できることがわかりました。

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)
1
acamino