Today i ran into a spec that needed to override a class constant in order to assert that its members are called by an iterator and used inside the code. It wasn’t simply an implementation detail as i needed to make sure everything was working as it should in a kind of complex environment.
At first, i thought of performing a class_eval to reset the constant, which did not work. Later on i’ve used const_set and as it worked it would send a warning that looked pretty ridiculous right in the middle of my specs: warning: already initialized constant A
A few hours later, after running into ruby-doc several times, i created a solution that seems to be working like a charm (at least until now!). It was made with the RSpec processing standards in mind but it should work with other testing frameworks as well by using the same logic:
# Stubbing class constants describe "stub class constants" do before(:all) do @new_constant = mock('new_constant') @old_constant = ClassThatHasTheConstant::Constant # saves the old constant for future resetting ClassThatHasTheConstant.__send__(:remove_const,'Constant') # tells the class to remove the constant through __send__ because :remove_const is a private method ClassThatHasTheConstant.const_set('Constant', @new_constant) # set a new constant with a new value end [ ... ] # your examples here after(:all) do ClassThatHasTheConstant.__send__(:remove_const,'Constant') ClassThatHasTheConstant.const_set('Constant', @old_constant) end end
Is there a better way to do this? Am i violating any principles of good programming? Please comment below!