I have a class that contains a bunch of methods, I have written unit tests for each method. The main method in the class is the encrypt
method, which takes a message and encrypts it. I have also written like 5 other methods that are used by this encrypt method, but I don't want the user to be able to call these methods, I just want to use them inside the encrypt method to get the job done, but I don't want the user to do like @obj.some_method_that_is_not_encrypt, I want to make only the encrypt
method invokable, I know I can make these methods private, but then my unit tests will fail. How do I go about dealing with this ?
Asked
Active
Viewed 63 times
0

Ahmad Al-kheat
- 1,805
- 2
- 16
- 25
-
1see here http://stackoverflow.com/questions/267237/whats-the-best-way-to-unit-test-protected-private-methods-in-ruby you can use send to get around the private. – Doon Apr 13 '15 at 16:56
-
@Doon but isn't this smelly? – Ahmad Al-kheat Apr 13 '15 at 16:58
-
2Smell determination is left as an exercise for the reader :) it opens up a whole new can of worms. But the fact that your (or your classes) users can do this and bypass private means private should be treated as a suggestion anyways. But alas I don't have a good answer for it.. I normally test the public interfaces / behavior of the class as opposed to each function, for right or wrong. – Doon Apr 13 '15 at 17:03
1 Answers
1
Your unit tests can use Object#send(...)
to invoke private methods:
class Foo
private
def bar
"ok"
end
end
f = Foo.new
f.bar # => NoMethodError: private method `bar' called...
f.send(:bar) # => "ok"
So your "encrypt" method could be the only public one but it can still use private methods which are not exposed to polite users of your library (they can, of course, use send
also if they want).
Note also that a peculiar aspect of "private" methods is that they cannot be invoked with an explicit receiver, even in the same class. So you could not call self.my_private_method
, instead you must simply call my_private_method
. For example:
class Foo
def foo
self.bar # => NoMethodError: private method `bar' called...
bar # => "ok"
end
private
def bar; "ok"; end
end

maerics
- 151,642
- 46
- 269
- 291