Ich benutze Factory Girl, um zwei Instanzen in meinem Modell-/Komponententest für eine Gruppe zu erstellen. Ich teste das Modell, um zu überprüfen, ob ein Aufruf von .current nur die 'aktuellen' Gruppen gemäß dem Ablaufattribut wie folgt zurückgibt.
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
Mein Problem ist, dass ich eine Validierung in dem Modell erhalten habe, die überprüft, ob der Ablauf einer neuen Gruppe nach dem heutigen Datum liegt. Dies führt zu einem Validierungsfehler.
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
Gibt es eine Möglichkeit, die Gruppe erzwungen zu erstellen oder die Validierung zu umgehen, wenn Sie Factory Girl erstellen?
Dies ist nicht spezifisch für FactoryGirl, aber Sie können Validierungen beim Speichern von Modellen immer mithilfe von save(:validate => false)
umgehen:
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
Ich bevorzuge diese Lösung aus https://github.com/thoughtbot/factory_girl/issues/578 .
In der Fabrik:
to_create {|instance| instance.save(validate: false) }
EDIT:
Wie in dem referenzierten Thread und in den Kommentaren/Lösungen anderer erwähnt, möchten Sie dies wahrscheinlich in einen Merkmalsblock einschließen, um Verwirrung/Probleme an anderen Stellen Ihrer Tests zu vermeiden. Zum Beispiel, wenn Sie Ihre Validierungen testen.
Es ist keine gute Idee, Validierungen standardmäßig im Werk zu überspringen. Einige Haare werden herausgezogen, um das herauszufinden.
Am schönsten finde ich:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Dann in deinem Test:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Für diesen spezifischen datumsbasierten Überprüfungsfall können Sie auch die Option timecop gem verwenden, um die Uhrzeit vorübergehend zu ändern, um den alten Datensatz zu simulieren, der in der Vergangenheit erstellt wurde.
foo = build(:foo).tap{ |u| u.save(validate: false) }
Abhängig von Ihrem Szenario können Sie die Überprüfung so ändern, dass sie nur bei der Aktualisierung erfolgt. Beispiel: :validates :expire_date, :presence => true, :on => [:update ]
Ihre Fabriken sollten standardmäßig gültige Objekte erstellen. Ich habe festgestellt, dass vorübergehende Attribute verwendet werden können, um eine bedingte Logik wie folgt hinzuzufügen:
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
In deinem Test:
create(:group, skip_validations: true)
Es ist nicht ratsam, die gesamte Validierung dieses Modells zu überspringen.
spec/factories/traits.rb
-Datei erstellen.
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
fix spez
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