Testing privates debate(?)

229 views
Skip to first unread message

Sebastian Larsson

unread,
Aug 25, 2013, 7:57:09 AM8/25/13
to clean-code...@googlegroups.com
Hi!


I know testing the private methods of an object is a "hot" topic. Some people say that you should not test private methods alone since they will be tested through the objects public interface. Others claim that you need to test private methods as well (the reason why PowerMock exists for example). 

My own opinion is that the more I can avoid testing private methods the better. One way of avoiding it is by applying dependency injection, looking for "hidden objects" that are disguised as private methods. Then I can turn those private methods into public methods of a separate object and then hide (compose) that object inside the object that previously contained the private method calls.

After having watched the lastest clean code episode (e21), it seems Uncle Bob is saying that we should never test private methods. In case they need to be tested, the encapsulation need to be elevated. In this case I imagine that some people might say that you should not make the design of the code worse for the sake of a test (which might also go against what Uncle Bob said - Tests trump Encapsulation). 

Maybe its time to look at the design of the system whenever you start thinking about testing privates? Is there even a debate? To me it feels like the nr 1 of the tests after reliability is that they conform to the OCP - that you can change production code without having to maintain test code.


Powermock: https://code.google.com/p/powermock/  (the first paragraph describes why we would need testing of privates)


BRs

Sebastian

Caio Fernando Bertoldi Paes de Andrade

unread,
Aug 25, 2013, 9:15:53 AM8/25/13
to clean-code...@googlegroups.com
Sebastian,

I have been practising TDD for a bit now, and I can use static, final and private classes or methods with no problems.
I never felt the need to test those individually, since I test the behaviour via the public methods in my use cases (interactors), which is what really matters from a user point of view.
This allows me to use whatever underlying implementation detail I think is best.

Cheers,
Caio

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at http://groups.google.com/group/clean-code-discussion.

Gabriele Tondi

unread,
Aug 25, 2013, 3:13:47 PM8/25/13
to clean-code...@googlegroups.com
Hi!

I agree with Caio, we should always test our API (intended as Application Public Interface, not as SOAP or REST etc).
Moreover we should test behaviors and not implementation... and privates and internals are usually implementations.

This video: http://vimeo.com/68375232 has been posted some topic ago and explain very well what we should test and how!

In PHP I had recently need to test a private method to verify the presence of a bug. So I'd write a "mock" class that extends the original one and witch exposes as public the target method.
The mock class is part of the test bundle, so the design of the main app as been remain unchanged.
After the test I think that is usually better to remove that mock because this is coupling my test suite on implementation in the main app.

Have fun with coding,
Gabriele

Jop van Raaij

unread,
Aug 26, 2013, 8:53:56 AM8/26/13
to clean-code...@googlegroups.com
I mostly agree, but when you feel you have to test a private method I think there is a strong smell you should look at your design. Creating a mock to extend something to make a method public? I don't understand how you would accomplish that. Maybe I misunderstand, but in Java it isn't possible to access a private method, except from the class itself. Extending the class does not make it accessible in the extended class! That's where protected would be used.

But why would you ever have to test a private method explicitly? A private method is usually (or always?) the result of refactoring. The most common situation for me is refactoring out a few lines out to a new private method. Instead of the method doEverythingAndThisAndThat(), you would separate it into multiple private methods, called from (probably) one public method. I always try to keep in mind the single responsibility principle and value readability a lot, like when moving code from an if statement to a separate method.
All code in the private methods is (still) covered by the unit tests which made you write the code in the first place.

I'd love to see a concrete example of a private method you would want to test explicitly :).

Rusi Filipov

unread,
Sep 8, 2013, 10:03:10 PM9/8/13
to clean-code...@googlegroups.com
If you really need to test a private method, in Java you could make it package-private and avoid heavy altirely like PowerMock. In my experience, the feeling of need to test private methods only emerges, when the class is overloaded with responsibilities and not focused to do a single thing. So in this case it is better to refactor the class first and then apply unit tests to the extracted parts, instead to harden the overloaded class more with unit tests. 

PS: keep out of heavy frameworks like PowerMock and JMockit. They make testing sub-optimal design possible, and this is exactly the problem. It leads to poor and fragile tests..

Sebastian Gozin

unread,
Sep 9, 2013, 5:14:44 AM9/9/13
to clean-code...@googlegroups.com
I agree with the feeling that PowerMock makes testing of sub optimal design possible. The pitch for PowerMock you linked to actually passes this sub optimal design of as good design which is where I think they are wrong. As others have pointed out a private shouldn't be so complex that it warrants testing on it's own. If it did then I think extracting it into a collaborator is probably the better design.

As a small anecdote.

I had on my team a few people who had recently discovered PowerMock and had started to use it to stub static methods and methods on the system under test with abandon. They absolutely loved being able to do this. That is until I was wondering why the build was taking over a minute to run. Considering the size of the application I felt it should run in under 10 seconds. So I checked the test report and there was a lot of tests which needed more than a second to complete even though nothing special was happening... except for PowerMock. So I removed all PowerMock related code from the test and used collaborators instead and the test suite dropped back under 10 seconds.

Basically, be aware that PowerMock allows you to do things you would not ordinarily do which may be necessary when dealing with legacy code but should otherwise be avoided and actively removed when possible.

- Sebastian

Rusi Filipov

unread,
Sep 9, 2013, 5:43:46 AM9/9/13
to clean-code...@googlegroups.com
We were also very enthusiastic when we first discovered JMockit, which can basically stub out everything you can think of, even methods like System.currentTimeMillis() or File.delete().

Experience taught us that tests that make use of mocking statics, or indirectly mocking distant parts of the object graph lead to poor isolation of the Object Under Test and are quite hard to understand when you look at them later. This is because they don't force you to simplify the Object Under Test and make its class small and focused. 

Perhaps as an initial step to a legacy module "power"-mocking is OK, but it should not be the default choice. Mockito for Java and Moq for C# are excellent examples of mocking frameworks, and the disability to mock out static and final stuff is actually a good thing.
Reply all
Reply to author
Forward
0 new messages