Подтвердить что ты не робот

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?

4b9b3361

Ответ 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