Factory-girl create that bypasses my model validation

怎甘沉沦 提交于 2019-12-02 16:28:26

This isn't very specific to FactoryGirl, but you can always bypass validations when saving models via 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

I prefer this solution from https://github.com/thoughtbot/factory_girl/issues/578.

Inside the factory:

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

EDIT:

As mentioned in the referenced thread, and by other's comments/solutions, you'll likely want to wrap this in a trait block to avoid confusion/issues elsewhere in your tests; for example, when you're testing your validations.

It's a bad idea to skip validations by default in factory. Some hair will be pulled out finding that.

The nicest way, I think:

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

Then in your test:

create(:group, :skip_validate, expiry: Time.now + 1.week)

For this specific date-baesd validation case, you could also use the timecop gem to temporarily alter time to simulate the old record being created in the past.

Chris Habgood
foo = build(:foo).tap{ |u| u.save(validate: false) }

Your factories should create valid objects by default. I found that transient attributes can be used to add conditional logic like this:

transient do
  skip_validations false
end

before :create do |instance, evaluator|
  instance.save(validate: false) if evaluator.skip_validations
end

In your test:

create(:group, skip_validations: true)

It is not best to skip all validation of that model.

create spec/factories/traits.rb file.

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

fix spec

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

Depending on your scenario you could change validation to happen only on update. Example: :validates :expire_date, :presence => true, :on => [:update ]

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!