Factory -girl create that bypasses my validation model

I use Factory Girl to create two instances in my / unit test model for a group. I am testing a model to verify that the .current call returns only the "current" groups according to the expiry attribute, as shown below ...

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 

My problem is that I received confirmation in a model that checks for the expiration of a new group after today's date. This causes the check below to fail.

  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 

Is there a way to force the creation of a group or circumvent the check when creating with Factory Girl?

+59
ruby-on-rails ruby-on-rails-3 rspec rspec-rails factory-bot
Feb 17 '12 at 3:10
source share
8 answers

This is not very specific to FactoryGirl, but you can always bypass checks when saving models with 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 
+71
Feb 17 2018-12-12T00:
source share

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 mentioned topic and in other comments / solutions, you probably want to enclose this in a dash block to avoid confusion / problems elsewhere in your tests; for example, when you test your checks.

+48
Aug 19 '14 at 19:52
source share

It is a bad idea to skip the default checks in the factory. Some hair will tear out when it is discovered.

The most enjoyable 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) 
+21
Aug 30 '17 at 16:49
source share

In this particular case of checking date-baesd, you can also use timecop gem to temporarily change the time to simulate an old record that was created in the past.

+6
Dec 19
source share
 foo = build(:foo).tap{ |u| u.save(validate: false) } 
+4
Feb 07 '16 at 22:19
source share

Depending on your scenario, you can change the validation only when updating. Example:: :validates :expire_date, :presence => true, :on => [:update ]

+1
Jun 28 '13 at 18:04 on
source share

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

 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) 
+1
Apr 28 '18 at 22:14
source share

It is not better to skip all checks of this model.

create spec/factories/traits.rb .

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

fix specification

 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 
0
Jan 26 '19 at 9:32
source share



All Articles