Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Redefine a class constant #13
I would like to mock a class constant but it does not work:
Is there any way to do something like this?
Mocha is only designed to work with methods, not constants.
I can think of at least 3 options :-
You might also want to consider whether you need to stub the constant at all. It might be sufficient (and more intention revealing) to reference the constant in your tests.
I hope that helps. Please close this issue if you are happy with the response.
I have done something like this:
There are a couple of warnings that with the Rails
Anyhow I still think that would be great if Mocha will offer to us the possibility of mocking a constant so we will can play with them on an easy way.
The points are, is this possible? do you think is a good idea to add this behavior to Mocha?. If both answers are yes I can try to help in this feature. If any answer is not you can close the issue :)
You are right about options 1 & 2 - my examples were just demonstrating what was possible - they don't return the constant to its initial state, but hopefully you can see this would be trivial to implement. I understand your reservations about option 3, but I'm not sure I completely agree - I'm always happy to change my application code to make testing easier.
Anyway, just to be clear, it certainly is possible to do what you want to do. However, just because something is possible, doesn't mean it's desirable!
Personally, I don't find I need to stub constants when writing tests, so it would be good to understand more about why you want to be able to do it. Can you give us a more real-world example? It's always easier to talk about something more concrete.
If it makes any sense for the value to change for the duration of a test, I would be inclined to store it in some kind of variable instead of a constant, but perhaps use a constant for the variable's default value.
Anyway, if you'd like to discuss this further and see if other people are interested in this feature, please drop us a line on the mailing list.
Still comes up high in google searches so FWIW here are my ¢2: wrap the constant in a class method
class Fetcher DATA_FILE = 'tmp/real_data.csv'.freeze # … def self.data_file DATA_FILE end end
that we can later stub in the test:
class FetcherTest < ActiveSupport::TestCase def setup Fetcher.stubs(:data_file).returns('test/fixtures/files/test_data.csv') end # … end
We test that custom slugs and formats get recognised and passed into the render method. We wrap the RootController Constants in methods so that we can stub them in the tests, as per freerange/mocha#13. We wondered whether it would be better to test the RootController constants CUSTOM_SLUGS and CUSTOM_FORMATS directly with their preset keys and values (so without stubbing), but were unsure if it would make the tests harder to read.
Just a small improvement on top of @grosser's method:
def stub_constant(klass, const, value) old = klass.const_get(const) klass.send(:remove_const, const) klass.const_set(const, value) yield ensure klass.send(:remove_const, const) klass.const_set(const, old) end
So you can now stub constants from different classes:
it 'actually sends notification messages on slack' do stub_constant(Notification, :SLACK_CHANNEL, '#test') do stub_constant(User, :ADMIN_SLACK_ID, '78UIMF1') do Notification.master_alert end end end