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を使用して作成するときに、グループを強制的に作成する方法や検証を回避する方法はありますか?
これは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)
この特定の日付ベースの検証の場合、 timecop gemを使用して一時的に時間を変更し、過去に作成された古いレコードをシミュレートすることもできます。
foo = build(:foo).tap{ |u| u.save(validate: false) }
そのモデルのすべての検証をスキップすることは最善ではありません。
作成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 ]
工場ではデフォルトで有効なオブジェクトを作成する必要があります。 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)