Girl de fábrica Crear que omita mi validación de modelo
-
27-10-2019 - |
Pregunta
Estoy usando Factory Girl para crear dos instancias en mi prueba de modelo/unidad para un grupo. Estoy probando el modelo para verificar que una llamada a .Current devuelve solo los grupos 'actuales' de acuerdo con el atributo de vencimiento según lo siguiente ...
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
Mi problema es que tengo validación en el modelo que verifica el vencimiento de un nuevo grupo es después de la fecha de hoy. Esto plantea la falla de validación a continuación.
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
¿Hay alguna manera de crear con fuerza el grupo o evitar la validación al crear Usar Factory Girl?
Solución
Esto no es muy específico para FactoryGirl, pero siempre puede evitar validaciones al guardar modelos a través de 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
Otros consejos
Prefiero esta solución de https://github.com/thoughtbot/factory_girl/issues/578.
Dentro de la fábrica:
to_create {|instance| instance.save(validate: false) }
EDITAR:
Como se menciona en el hilo referenciado, y por los comentarios/soluciones de otros, es probable que desee envolver esto en un bloque de rasgos para evitar confusiones/problemas en otras partes de sus pruebas; Por ejemplo, cuando está probando sus validaciones.
Es una mala idea omitir validaciones por defecto en fábrica. Se sacará un cabello al encontrar eso.
La forma más bonita, creo:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Luego en tu prueba:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Para este caso específico de validación de fecha de fecha, también puede usar el punto de vista GEM para alterar temporalmente el tiempo para simular el antiguo registro que se crea en el pasado.
foo = build(:foo).tap{ |u| u.save(validate: false) }
Sus fábricas deben crear objetos válidos de forma predeterminada. encontre eso atributos transitorios se puede usar para agregar lógica condicional como esta:
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
En tu prueba:
create(:group, skip_validations: true)
No es mejor omitir toda la validación de ese modelo.
crear spec/factories/traits.rb
expediente.
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
arreglar especificaciones
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
Dependiendo de su escenario, puede cambiar la validación para que ocurra solo en la actualización. Ejemplo: :validates :expire_date, :presence => true, :on => [:update ]