Testing private classes in Java

Posted on September 1, 2007
Filed Under Uncategorized | 10 Comments

When you’re doing test driven development you often run into the issue where you want to test package level classes and/or private/protected/package level methods on classes.  So what do you do?  Either you open up your design to make them testable or you use JUnitX.  Given that I don’t think it is a good idea generally to over expose yourself in public, I tend to go with JUnitX.  Better for you.  Better for me :-)

 

Here’s what my test code looks like (which lives in its own unique test package):

 

public class MyTest extends PrivateTestCase

{

….

public void testPrivateMethodCall() throws Exception
{
    // where Coffee is a private class within the package
    Object privateClass = newInstance(”com.cognifide.cafe.Coffee”, NOARGS);

 

    // AND drink is a private method on Coffee
    invoke(privateClass, “drink”, NOARGS);
}

}

Unfortunately, it is a bit quirky, and you have to create a boiler plate TestProxy class in the package for all classes that you want to test in this way.  But I’ve taken a look at the source and you can get round this by tinkering with junitx.framwork.TestProxyFactory.createProxyFor().  I just haven’t got round to doing it.  If you do, please drop me a line and send me your patch…

Comments

10 Responses to “Testing private classes in Java”

  1. prozz on September 5th, 2007 9:18 am

    Why do you need to test private methods? Usually we want to test overall usability of a class, so it means to test against interface methods it implements. Am I right or this scenario applies only to perfect world? :)

  2. cleve on September 5th, 2007 11:51 am

    In you’re perfect world you only every test against interfaces, but implementation classes tend to be a little trickier.

    How do you unit test those to the level that you’re confident with? How do you test your private helper methods on this implementation class? Yes, you could do it indirectly through a higher level abstraction, but to me that is not unit testing the implementation class directly.

    If I can write a test that tests the helper method directly, then i would prefer to do that, rather than some interface, that will call through to my private methods, doing who knows what before and/or after the call…

  3. prozz on September 5th, 2007 12:35 pm

    The question is if I really need to test such ‘private helper methods’.

    How about:
    - moving such private methods to some utility class
    - making them protected to allow testing and reusability in future?

    Of course everything depends on implementation, probably your approach is correct. However I have to admit I never need to test this way.

  4. cleve on September 5th, 2007 1:43 pm

    So you would prefer to artificially break up a perfectly good class to make it testable? So would I. But if there are tools around that enable me to maintain my design and keep it testable, i suppose i’d do that.

    I not really hung up on keeping this private. Keeping things testable is more important…

  5. Merlyn Albery-Speyer on September 7th, 2007 6:01 am

    I don’t mean to be overly harsh here, but anyone who feels the need to test private methods really hasn’t gotten to grips with TDD yet.

  6. cleve on September 7th, 2007 6:19 am

    ha ha ha.

    how funny merlyn. i would have expected nothing less from a purist.

    anyway, strange as it seems, this discussion came up at a conference I attended and the room was divided from people that have been doing TDD for many years (more so on the private method side). People i kind of respect as well.

    I don’ think it is as clear cut as ‘if you test private, you haven’t got TDD. That’s the sort of think that makes my skin shudder in a similar way when I hear agile folks say, if your projects failing, you not doing agile right.

    pragmatically, on projects, i don’t think its a black and white as you’re painting it…

  7. Merlyn Albery-Speyer on September 8th, 2007 6:24 pm

    Yes, I guess it probably is the purist line too.

    What reaffirms it for me though is that I haven’t found myself wishing I could test a private method since I was very new to TDD.

    In fact I don’t see how you can arrive at the idea of even wanting to testing a private method with TDD. What would the thought process look like?

    The way I’m assuming the situation arises would be something along these lines (when someone is only really paying lip service to their tests as opposed to being driven by them):

    You’re writing your tests last and then it becomes apparent that you have some significant logic that’s used by more than one method you want to test, and because it’s all so unwieldy to tackle the problem all in one go now that you “have the code working anyway” the inclination is to work around the design problem by making your test dive into the internals of the class.

  8. Merlyn Albery-Speyer on September 8th, 2007 6:43 pm

    Ok. There’s another possibility which would then come down to personal design taste: Your design philosophy prohibits you from extracting behaviour from a class because then it would become visible to users of your package which you consider to be a bad thing.

    In that case I’d take issue with the design approach and not so much the testing of private classes / methods.

  9. cleve on September 8th, 2007 7:11 pm

    Nope. I said I was not anal about encapsulation. It would be more important for me to know that stuff was testable.

    Also, for integration and/or migration projects, where you don’t have complete control over code base and you are working with third party assets and the like, such tools are useful.

    I most certainly am not a purist, more pragmatic and ultimately delivery focussed I suppose…

  10. Merlyn Albery-Speyer on September 9th, 2007 7:41 am

    Here are two different opinions on the topic from the XPDX discussion group:

    Ward Cunningham (http://tech.groups.yahoo.com/group/xpportland/message/1201)

    “No, I’ve never had this problem [of wanting to test private methods].”

    Jim Shore (http://tech.groups.yahoo.com/group/xpportland/message/1204)

    “It comes down to a tension between the desire to TDD and the desire to follow a strict access model. One approach is to ignore the access model and just make things public when you need to test them. I prefer not to do that because the access keywords (public/private/etc) provide hints to future programmers about the my thought process. Still, I’ll do it when I have to.”

Leave a Reply