Skip callbacks on Factory Girl and Rspec

前端 未结 16 1051
暗喜
暗喜 2020-12-12 12:17

I\'m testing a model with an after create callback that I\'d like to run only on some occasions while testing. How can I skip/run callbacks from a factory?

c         


        
16条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-12 13:04

    I'd like to make an improvement to @luizbranco 's answer to make after_save callback more reusable when creating other users.

    FactoryGirl.define do
      factory :user do
        first_name "Luiz"
        last_name "Branco"
        #...
    
        after(:build) { |user| 
          user.class.skip_callback(:create, 
                                   :after, 
                                   :run_something1,
                                   :run_something2) 
        }
    
        trait :with_after_save_callback do
          after(:build) { |user| 
            user.class.set_callback(:create, 
                                    :after, 
                                    :run_something1,
                                    :run_something2) 
          }
        end
      end
    end
    

    Running without after_save callback:

    FactoryGirl.create(:user)
    

    Running with after_save callback:

    FactoryGirl.create(:user, :with_after_save_callback)
    

    In my test, I prefer to create users without the callback by default because the methods used run extra stuff I don't normally want in my test examples.

    ----------UPDATE------------ I stopped using skip_callback because there were some inconsistency issues in the test suite.

    Alternative Solution 1 (use of stub and unstub):

    after(:build) { |user| 
      user.class.any_instance.stub(:run_something1)
      user.class.any_instance.stub(:run_something2)
    }
    
    trait :with_after_save_callback do
      after(:build) { |user| 
        user.class.any_instance.unstub(:run_something1)
        user.class.any_instance.unstub(:run_something2)
      }
    end
    

    Alternative Solution 2 (my preferred approach):

    after(:build) { |user| 
      class << user
        def run_something1; true; end
        def run_something2; true; end
      end
    }
    
    trait :with_after_save_callback do
      after(:build) { |user| 
        class << user
          def run_something1; super; end
          def run_something2; super; end
        end
      }
    end
    

提交回复
热议问题