Fabbrica-girl creare che aggira il mio modello di convalida
-
27-10-2019 - |
Domanda
Sto usando Factory Girl per creare due istanze nel mio test di modello / unità per un gruppo. Sto testando il modello di verificare che una chiamata a rendimenti .Current solo i gruppi 'corrente' in base all'attributo di scadenza di cui al di sotto ...
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
Il mio problema è che ho la validazione del modello che i controlli di scadenza di un nuovo gruppo è dopo la data di oggi. Ciò solleva l'errore di convalida di seguito.
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
C'è un modo per forza creare il gruppo o aggirare la convalida durante la creazione utilizzando Factory Girl?
Soluzione
Questo non è molto specifico per factorygirl, ma si può sempre bypass convalide durante il salvataggio di modelli tramite 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
Altri suggerimenti
Io preferisco questa soluzione da https://github.com/thoughtbot/factory_girl/issues/578 .
All'interno della fabbrica:
to_create {|instance| instance.save(validate: false) }
Modifica
Come accennato nel thread di riferimento, e da altri di commenti / soluzioni, è probabile che vuole avvolgere questo in un blocco di carattere per evitare confusione / problemi in altre parti i test; per esempio, quando si sta testando le vostre convalide.
E 'una cattiva idea di saltare le convalide per impostazione predefinita in fabbrica. Alcuni capelli sarà tirato fuori trovando che.
Il modo più bello, penso:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Poi nel test:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Per questo specifico caso la convalida della data-baesd, si potrebbe anche utilizzare il Timecop gioiello in tanto temporaneamente alter per simulare il vecchio record di essere creato in passato.
foo = build(:foo).tap{ |u| u.save(validate: false) }
I tuoi fabbriche dovrebbero creare oggetti validi per impostazione predefinita. Ho scoperto che transitoria attributi può essere utilizzato per aggiungere logica condizionale in questo modo:
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
Nel test:
create(:group, skip_validations: true)
Non è meglio saltare tutta la convalida di quel modello.
creare il file spec/factories/traits.rb
.
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
fix spec
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
A seconda dello scenario che si potrebbe cambiare la convalida per accadere solo su aggiornamento. Esempio: :validates :expire_date, :presence => true, :on => [:update ]