Фабрично-заводская девушка, которая обходит мою модель проверки - PullRequest
66 голосов
/ 17 февраля 2012

Я использую Factory Girl для создания двух экземпляров в моей модели / модульном тесте для группы. Я тестирую модель, чтобы убедиться, что вызов .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?

Ответы [ 8 ]

78 голосов
/ 17 февраля 2012

Это не очень специфично для 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
49 голосов
/ 19 августа 2014

Я предпочитаю это решение от https://github.com/thoughtbot/factory_girl/issues/578.

Внутри завода:

to_create {|instance| instance.save(validate: false) }

EDIT:

Как упоминалось в упомянутой теме и в комментариях / решениях других, вы, вероятно, захотите заключить это в блок черты, чтобы избежать путаницы / проблем в других местах ваших тестов; например, когда вы проверяете свои проверки.

22 голосов
/ 30 августа 2017

Это плохая идея, чтобы пропустить проверки по умолчанию на заводе.Некоторые волосы будут вырваны, обнаружив это.

Самый хороший способ, я думаю:

trait :skip_validate do
  to_create {|instance| instance.save(validate: false)}
end

Тогда в вашем тесте:

create(:group, :skip_validate, expiry: Time.now + 1.week)
7 голосов
/ 20 декабря 2012

Для этого конкретного случая проверки даты-baesd вы также можете использовать гем timecop , чтобы временно изменить время для имитации старой записи, создаваемой в прошлом.

4 голосов
/ 08 февраля 2016
foo = build(:foo).tap{ |u| u.save(validate: false) }
2 голосов
/ 26 января 2019

Не лучше пропустить все проверки этой модели.

создать 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
1 голос
/ 29 апреля 2018

Ваши фабрики должны создавать действительные объекты по умолчанию. Я обнаружил, что временные атрибуты могут использоваться для добавления условной логики, например:

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)
1 голос
/ 28 июня 2013

В зависимости от вашего сценария вы можете изменить проверку, чтобы она выполнялась только при обновлении.Пример: :validates :expire_date, :presence => true, :on => [:update ]

...