Summary:
This article compares four different approaches to testing private methods in Java classes.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: April 28, 2015 4:22 PM by
Syed
|
Nice article; I've wanted to see a discussion on these categorizations for some time now. Some random thoughts:
-I've used all but the third technique (inner test class). The only time I've found the reflective cheat useful enough to warrant the ugliness is in an "assertFieldsEqual" method.
-If I'm building a private method that is so complex that I need to address its functionality separately (i.e. such that I can't effectively create it through testing of the public interface), I've found that more often than not it contains some commonly useful abstraction. So I'll typically expose it to package level and write the test. Then, *depending on my level of laziness*, and the extent to which I think I've found something useful, I'll extract it to a separate class.
I don't have a problem with a one-method, single-use utility class. Theoretically, I'm not gonna need it. What I find, though, is that the existence of this class often triggers other developers to notice it and use the common abstraction. (Pairing doesn't always catch everything.)
-The bigger sin than exposing a private method to package level access is the tighter coupling that comes as a result of testing implementation details. The technique--whether you change the access modifier or use reflection--doesn't matter. I can trust that developers of classes in the same package won't abuse the exposed method (and if they do, so what; that's why I have tests). That's not what I'm worried about; perfect design be damned. The problem is that you can no longer refactor the production class as easily.
On occasion, this is OK. Taken too far, your system becomes stagnant and brittle, something I've seen in practice. Small refactorings that should take seconds and should have no impact instead break tests, which then require tens of minutes of attention. (This is an even bigger problem when people similarly violate encapsulation using "method-sequence mocking.")
-Jeff-
|
|
|
I don't test private methods. But I know when they are tested (or not); if you use a code coverage tool like Clover (or others) you will find out exactly when a private method is not covered in your tests and when particular code blocks aren't tested. You'll discover all the little boundary conditions and funny little combinations that you have to add to your tests in order to ensure your class maintains all of its expected behaviour. And you'll test your private methods, or at least know if it isn't, and exactly what parts of it aren't, being tested.
|
|
|
Hi Bill,
I quite enjoy your articles and am patiently awaiting the completion of your book(s). However, regarding this topic, I'd like to point out what I consider to be a violation of a unit testing "tenet" (if I may call it that), regardless of the scope of the method(s) under test.
Perhaps you have done this for the sake of brevity in your article, but I noticed that your test method (testParseArgsIntoLists) actually consists of 7 distinct tests. Best practice (as far as I know it) dictates that each test should exist within a distinct test method. By placing them all into a single monolithic test method, you not only obscure the distinction between the individual tests, but you also create an "all or nothing" test.
This means that if one of the 7 tests fail, they all fail in a sense. That is, you are unable to readily see that perhaps 6 of the 7 might actually succeed and therefore cannot as quickly identify the particular test that failed.
More precisely, all tests (in your monolithic test method) that follow the failed test will remain untested until the failed test is made to pass, so you will never see all failures and all successes at once, as you would if you used 7 separate test methods.
Sorry this is a bit off topic, but I thought it was worth pointing out.
Cheers, Chuck
|
|
|
> In particular, any method that is capable of producing > different results depending upon a set of parameters or > other conditions should have a set of tests that cover all > the variations. Those tests should limit themselves to > the method being tested and should not be encumbered with > the added complexity of having to manipulate the public > interface in order to induce specific behaviour in hidden > methods. > > Further tests may be necessary to ensure that the > private methods work as intended via the public interface > but that is a separate issue to demonstrating that those > methods work in their own right.
I really enjoyed the original article and was excited to see someone wrestling with an issue that had bugged me for a long time. I too saw the majority telling me that its "wrong" to test anything but the public interface of a class. However that approach left me feeling unsatisfied.
The poster above nicely elucidates the primary point in my mind: The point of unit testing is to isolate a "unit" (a method in this case) and exercise it. By doing so we immediately pinpoint the root cause of a failure. In contrast, a more black-boxish system/functional test might illustrate a failure condition in a system but it often requires research to determine the root cause of the failure. I want as much precision in my testing as possible to avoid this haze.
Testing of a private method is obviously a more direct test of that unit (method) then the indirect test we get by testing the public methods that use it.
In the past I've either skipped writing tests for the private scoped methods or (rarely) relaxed the scoping to package-level. I have looked at reflection-based approaches as mentioned in the article but to me that's just too much effort and complexity... it should not be that hard.
I've just started using the excellent open-source code coverage tool, emma. Perhaps having a tool confirm that my indirectly invoked private methods are being exercised will make me relax my stance.
It just smells so ... accidental.
I'm willing to be swayed and some of the points made in this thread were fairly compelling. I'm really enjoying this discussion.
|
|
|
Excellent article and interesting discussion. One approach I've been using in C# / Nunit is to promote private methods that I feel need to be tested to protected and then write a test class that overrides them. The test class method can access the base method implementation and either provide external visibility to it or implement the test logic itself.
I find this approach also works well for hooking in 'mock methods' that override methods that e.g. access hardware or some external API with code that can be driven by the test framework via public test properties that only exist in the test class. In some cases these mock methods are simpler to implement and maintain than full-blown mock objects.
The downside is that classes outside of the package can override the protected method as well, but it does leave the package-level and public API alone. Any potential issues with doing this in Java / JUnit?
|
|
|
> This article compares four different approaches to testing > private methods in Java classes. > > http://www.artima.com/suiterunner/private.html> > Do you test private methods? If not, why not? If so, how > do you prefer to test them? Using method invokeStaticMethod() I was able to invoke private methods, but at the same time I need to access private variables to check the results of the test.Is it possible to get access to private variables, If so please tell me the method of doing it. Anyway using Junit I was able to invoke the private method,but when tried to launch through ant, the private accessibility would be detected and the ant build would fail.How to overcome this problem? Kindly let me know as soon as possible as, I am working on the same concept. Thanks, Sreedevi.
|
|
|
Do you konw what kind of companies can be setted up in China? There are three different business incorporation vehicles which can be utilised to do business in China. These are: 1. The utilisation of a representative office 2. Seeking a Chinese joint venture partner 3. Establishing a Wholly Foreign Owned Enterprise (WFOE) Representative Office (RO): A representative office is just a subsidiary of a foreign company in China. If your are looking for a company, which needs a local presence to manage services or coordinate outsourcing business activities or research developing Chinese market, then a representative office is useful and inexpensive vehicles for establishing a presence in China. Main purposes of a representative office are conducting market research, monitoring purchasing activities, marketing and sales administration for sales conducted between China and your parent company etc. Representative offices cannot write bill for service or sales to their clients in China. However, you can act like a liaison in matter of ordering, shipping, collecting money and so on. Joint Venture: Joint venture is business where a foreign firm goes into businesses with local Chinese partners. Joint venture is usually established to exploit the market knowledge, preferential market treatment, and manufacturing capability of the Chinese side along with the technology, manufacturing know-how and marketing experience of the foreign partner. Wholly Foreign Owned Enterprise (WFOE): These are 100% foreign owned companies, originally developed for the specific purpose of encouraging foreign investment in manufacturing for export in Special Economic Zones (SEZs) in China, and they were prohibited from selling to the Chinese domestic market. Since a recent change in regulations, from 1 December 2004, WFOE's can now trade within China, and can sell wholly foreign manufactured goods in China. The capital requirements for such companies have also been dramatically reduced. so next time i will explain the benefits and disadvantages of them. If you are interested and want to konw more konwlege about it, you can goto the pages, we offer you four language websites: http://www.cityscopeinvestments.comChinese one: http://www.cityscopeinvestments.cnGerman one: http://www.cityscopeinvestments.deFrench one: http://www.cityscopeinvestments.com/indexfr.htmand also you can contact us if you have questions: email:s.xie@cityscopeinvestments.com tel:+86 (21) 63298968 fax:+86 (21) 63295886 we will ensure to answer your questions in ten minutes!
|
|
|
As long as the private methods are the part of internal class inplementation, it could not be a business of unit tests to test them. But I do agree with the concept claiming that the testing of private methods is sometimes defensible and desirable thing. So, I suggest to use following approach: the class that have privates are need to be tested tests itself.
Something like that:
ClassA { private methodA(); private methodB();
public TestItself() { // test methodA // test methodB
// if some test fails then throw an exception of some type, specifying numbers of tests that failed } }
So, the unit test can only invoke the testItself() method of ClassA
This allows us to test privates and do not violate the incapsulation
|
|
|
Hi,
It is an excellent article, very well written and the arguments very well explained. I thoroughly enjoyed reading it.
Until recently I did not test private methods, especially for classes that I had personally designed as I could ensure coverage of private methods via public methods within the test cases.
Recently I was asked to migrate legacy code from one database platform to another. To optimise the entire exercise while keeping the code change to the absolute minimum, it was decided to only test the methods that were changed. Quite a lot of database access code is locked in private methods and these methods needed to be tested separately to validate the change.
I used reflection successfully to invoke these methods and also to inspect the values of class fields before and after the tests.
Reflection is, therefore in my opinion, probably an efficient and an appropriate mechanism to test a legacy class's private members where minimum change is required.
|
|
|
I just thought to bring to your attention a new embodiment of Approach 4: dp4j.com which injects the reflection API code at compile-time.
|
|
|
I have written test code using java reflection and JUnit with your reference code at suitrunner. But now I am stuck at one place where I want to test Handler(java.os.Handler). So I have written one Handler and its handleMessage() and passed it to invocation method to invoke private method of target class. But that private method is not sending Message back to the handler that I have written. What is the best way to invoke private Handlers? Reply ASAP.
|
|
|
Hello I am trying to figure out, after reading your article what to do with my code and how to improve it, I posted it at stackoverflow: http://stackoverflow.com/questions/29908171/junit-test-for-private-methodMy code is like this: ****************************************************** public class DelegateHandler{ Map<Integer,ActionHandlers> handlerMaps;
public execute(Action action){ populateActionHandlers(action); executeActionHandlers();
}//end of execute
//This method can create and populate more than one handlers in handlerMap private populateActionHandlers(action){ handlerMap = new LinkedHashMap<ActionHandlers>(); if (action.isMultimode()){ handlerMap.add(1,new handler(action.getabc())); handlerMap.add(2,new handler(action.getabc()-1)); }else{ handlerMap.add(1,new handler(action)); }
}//end of populateActionHandlers
//This method can execute more than one handlers in handlerMap private executeActionHandlers(){ for(ActionHandler actionHandler : handlerMap.values){ actionHandler.executeAction(); }
}//end of executeActionHandlers } ******************************************** Can you tell me how to solve the code smell. i will really appreciate it. btw, I liked your blog article and I am trying to improve my code style and esp JUNIT tests. thanks Syed
|
|