Заводская девушка создает, которая обходит мою модель проверку
-
27-10-2019 - |
Вопрос
Я использую Factory Girl для создания двух экземпляров в моем модели/модельном тесте для группы. Я тестирую модель, чтобы проверить, что вызов .current возвращает только «текущие» группы в соответствии с атрибутом истечения срока действия, согласно ниже ...
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
Моя проблема в том, что у меня есть проверка в модели, которая проверяет истечение срока действия новой группы после сегодняшней даты. Это повышает сбой проверки ниже.
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
Есть ли способ насильственно создать группу или обойти подтверждение при создании с использованием Factory Girl?
Решение
Это не очень специфично для FactoryGirl, но вы всегда можете обойти проверку при сохранении моделей через 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
Другие советы
Я предпочитаю это решение от https://github.com/thoughtbot/factory_girl/issues/578.
Внутри фабрики:
to_create {|instance| instance.save(validate: false) }
РЕДАКТИРОВАТЬ:
Как упоминалось в упомянутом потоке, и в результате комментариев/решений других, вы, вероятно, захотите обернуть это в блок признаков, чтобы избежать путаницы/проблем в других местах ваших тестов; Например, когда вы тестируете ваши проверки.
Это плохая идея - по умолчанию пропустить проверки на заводе. Некоторые волосы будут вытащены, обнаружив это.
Самый приятный способ, я думаю:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Затем в вашем тесте:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Для этого конкретного случая проверки Date-BAESD вы также можете использовать Timecop драгоценный камень временно изменить время для моделирования старой записи, созданной в прошлом.
foo = build(:foo).tap{ |u| u.save(validate: false) }
Ваши фабрики должны создавать действительные объекты по умолчанию. я нашел это Переходные атрибуты можно использовать для добавления условной логики, как это:
transient do
skip_validations false
end
before :create do |instance, evaluator|
instance.save(validate: false) if evaluator.skip_validations
end
В вашем тесте:
create(:group, skip_validations: true)
Не лучше пропустить всю проверку этой модели.
Создайте spec/factories/traits.rb
файл.
FactoryBot.define do
trait :skip_validate do
to_create { |instance| instance.save(validate: false) }
end
end
Исправить спецификацию
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
В зависимости от вашего сценария вы можете изменить проверку, чтобы произойти только при обновлении. Пример: :validates :expire_date, :presence => true, :on => [:update ]