Question

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 au retour .Current seuls les groupes « courants » selon l'attribut d'expiration comme 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 j'ai validation dans le modèle qui vérifie l'expiration d'un nouveau groupe est postérieure à la date d'aujourd'hui. 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

Est-il possible de créer avec force le groupe ou contourner la validation lors de la création en utilisant Factory Girl?

Était-ce utile?

La solution

Ce n'est pas très spécifique à factorygirl, mais vous pouvez toujours contourner lors de l'enregistrement des modèles de validation 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

Autres conseils

Je préfère cette solution de https://github.com/thoughtbot/factory_girl/issues/578 .

A l'intérieur de l'usine:

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

EDIT:

Comme mentionné dans le fil référencé, et par d'autres solutions de commentaires /, vous voudrez sans doute envelopper ce dans un bloc de trait pour éviter toute confusion / problèmes ailleurs dans vos tests; par exemple, lorsque vous testez validateurs.

Il est une mauvaise idée de sauter par défaut dans la validation usine. Certains cheveux seront tiré constater que.

La plus belle façon, je pense:

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

Ensuite, dans votre test:

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

Pour cette date-baesd cas de validation spécifique, vous pouvez également utiliser la pierre précieuse Timecop pour modifier temporairement le temps pour simuler l'ancien record en cours de création dans le passé.

foo = build(:foo).tap{ |u| u.save(validate: false) }

Vos usines devraient créer des objets valides par défaut. J'ai trouvé que transitoire attributs peut être utilisé pour ajouter la 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 sauter toutes la validation de ce modèle.

créer un fichier spec/factories/traits.rb.

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

spec fix

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

En fonction de votre scénario vous pouvez changer la validation de se produire uniquement sur la mise à jour. Exemple: :validates :expire_date, :presence => true, :on => [:update ]

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top