Factory -girl создать, что обходит мою модель проверки
Я использую Factory Girl для создания двух экземпляров в моей модели /unit test для группы. Я тестирую модель, чтобы проверить, что вызов .current возвращает только "текущие" группы в соответствии с атрибутом expiry, как показано ниже...
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?
Ответы
Ответ 1
Это не очень специфично для 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
Ответ 2
Я предпочитаю это решение из https://github.com/thoughtbot/factory_girl/issues/578.
Внутри фабрики:
to_create {|instance| instance.save(validate: false) }
РЕДАКТИРОВАТЬ:
Как упоминалось в упомянутой теме и в других комментариях/решениях, вы, вероятно, захотите заключить это в блок черты, чтобы избежать путаницы/проблем в других местах ваших тестов; например, когда вы тестируете свои проверки.
Ответ 3
Плохая идея пропустить проверки по умолчанию в factory. Некоторые волосы вырвутся, обнаружив это.
Самый приятный способ, я думаю:
trait :skip_validate do
to_create {|instance| instance.save(validate: false)}
end
Затем в вашем тесте:
create(:group, :skip_validate, expiry: Time.now + 1.week)
Ответ 4
В этом конкретном случае проверки даты-baesd вы также можете использовать timecop gem, чтобы временно изменить время, чтобы смоделировать старую запись, являющуюся созданный в прошлом.
Ответ 5
foo = build(:foo).tap{ |u| u.save(validate: false) }
Ответ 6
В зависимости от вашего сценария вы можете изменить валидацию только при обновлении. Пример: :validates :expire_date, :presence => true, :on => [:update ]
Ответ 7
Ваши фабрики должны создавать действительные объекты по умолчанию. Я обнаружил, что временные атрибуты могут быть использованы для добавления условной логики, например так:
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)
Ответ 8
Не лучше пропустить все проверки этой модели.
создать файл 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