7

Is there a better way to clean class variables in between Rspec tests than to clear them explicitely from the after(:each) method? I would prefer a way that "clears them all", instead of having to remember adding them to the config.after every time again...

config.after(:each) do
  DatabaseCleaner.clean

  Currency.class_variable_set :@@default, nil
end
Danny
  • 5,945
  • 4
  • 32
  • 52

3 Answers3

6

I finally implemented this by defining a method in lib/auto_clean_class_variables.rb to reset all class variables of a given class

module AutoCleanClassVariables
  def reset_class_variables
    self::CLASS_VARIABLES_TO_CLEAN.each do |var|
      class_variable_set var, nil
    end
  end
end

and calling this method from within config.after(:each), located in spec_helper.rb

config.append_after(:each) do
  DatabaseCleaner.clean

  # Find all ActiveRecord classes having :reset_class_variables defined
  classes = ActiveSupport::DescendantsTracker.descendants(ActiveRecord::Base)
  classes.each do |cl|
    if cl.methods.include?(:reset_class_variables)
      cl.reset_class_variables
    end
  end
end

The models that need "cleaning" can bootstrap this behaviour:

extend AutoCleanClassVariables
CLASS_VARIABLES_TO_CLEAN = [:@@default]

This way everything works fine, and there is no (unnecessary) reload of the class leading to problems if you try to compare objects of these classes with each other (see my earlier comment)

Danny
  • 5,945
  • 4
  • 32
  • 52
4

You should be able to reload the class after every run:

after(:each) do
  Object.send(:remove_const, 'Currency')
  load 'currency.rb'
end

See: RSpec Class Variable Testing

Community
  • 1
  • 1
Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82
  • It looks like this breaks a test like def default? self == Currency.default end as the "old" and the "new" instance of the Currency class can not be compared anymore... I finally ended making a "delete_class_vars" method, like def delete_class_vars(classname) cl = classname.camelize.constantize cl.class_variables.each do |class_var| cl.class_variable_set class_var, nil end end – Danny Sep 29 '13 at 10:19
1

include this in your spec_helper.rb

Spec::Runner.configure do |config|
  config.before(:all) {}
  config.before(:each) {
       Class.class_variable_set :@@variable, value
  }
  config.after(:all) {}
  config.after(:each) {}
end

This will run what you choose before every different test. The accepted solution did not solve at least 2 cases I had where I needed a class variable reset.

Christopher Reid
  • 4,318
  • 3
  • 35
  • 74