J'utilise Factory Girl pour créer deux instances dans mon modèle/test unitaire pour un groupe. Je teste le modèle pour vérifier qu'un appel à .current ne renvoie que les groupes "actuels" en fonction de l'attribut d'expiration décrit ci-dessous ...
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
Mon problème est que le modèle vérifie que l'expiration d'un nouveau groupe est postérieure à la date du jour. Cela soulève l'échec de validation ci-dessous.
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
Existe-t-il un moyen de forcer la création du groupe ou de contourner la validation lors de la création à l'aide de Factory Girl?
Ce n'est pas très spécifique à FactoryGirl, mais vous pouvez toujours contourner les validations lors de l'enregistrement de modèles via 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
Je préfère cette solution de https://github.com/thoughtbot/factory_girl/issues/578 .
À l'intérieur de l'usine:
to_create {|instance| instance.save(validate: false) }
MODIFIER:
Comme mentionné dans le fil de discussion, et dans les commentaires/solutions d'autres personnes, vous voudrez probablement envelopper ceci dans un bloc de traits pour éviter toute confusion/problème ailleurs dans vos tests; par exemple, lorsque vous testez vos validations.
Ignorer les validations en usine est une mauvaise idée. Certains cheveux seront arrachés pour le trouver.
Le meilleur moyen, je pense:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Puis dans votre test:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Pour ce cas de validation spécifique basé sur la date, vous pouvez également utiliser la gemme timecop pour modifier temporairement le temps afin de simuler l'ancien enregistrement créé précédemment.
foo = build(:foo).tap{ |u| u.save(validate: false) }
En fonction de votre scénario, vous pouvez modifier la validation afin qu'elle ne se produise que lors de la mise à jour. Exemple: :validates :expire_date, :presence => true, :on => [:update ]
Vos usines devraient créer des objets valides par défaut. J'ai trouvé que les attributs transitoires peuvent être utilisés pour ajouter une logique conditionnelle comme ceci:
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
Dans votre test:
create(:group, skip_validations: true)
Il est préférable de ne pas passer toute la validation de ce modèle.
créer le fichier spec/factories/traits.rb
.
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
fixer la spécification
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