wake-up-neo.com

Fabrikmädchen erstellen, das meine Modellvalidierung umgeht

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?

59
Norto23

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
72
Brandan

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.

49
Jason Denney

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)
21
Tim Scott

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.

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

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 ]

1
JoaoHornburg

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

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
0
HAZI