Заводская девушка создает, которая обходит мою модель проверку

StackOverflow https://stackoverflow.com/questions/9322353

Вопрос

Я использую 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 ]

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top