Test Your Privates with JUnit

Recently at work, there’s been spirited discussion about process improvement. One such discussion centered on test driven development and its benefits. I’m not convinced it’s the consummate software development paradigm (writing a test before writing code still seems exactly backwards), but a healthy emphasis on testing cannot be all bad.

Essential to test driven development, at least in the Java realm, is the JUnit framework. I had sparsely used JUnit before and liked it, but for several reasons (none of them wholly legitimate), I stopped before fully exploring its potential.

Despite some mild resistance from some colleagues (“We don’t have time”) and with a strong desire to avoid repeating questionable development practices, I took up JUnit again. It didn’t take long before I ran into an interesting problem. How do I test a private method from within a TestCase?

As far as I could tell, I had limited options:

  • I wrote a protected method, testMyMethod(), whose sole purpose was to call myMethod(). This worked well since my test resided in the same package (albeit a different source directory), but I was uncomfortable with making code changes just for testing. In addition, the original method was now exposed via proxy.
  • I changed myMethod() access from private to protected. This was less intrusive, but I strongly preferred not to expose the method to other classes, even in the same package. The dilemma, of course, was that myMethod() was hidden from all classes, including my TestCase.
  • My last option was to give JUnit a pass altogether and write a main() method to contain all test code. I know many developers test this way, but JUnit’s features are just too good to ignore and passing desired parameters other than Strings into main() is impossible.

Having no satisfactory answer of my own, a colleague remembered hearing there was a way around this problem using reflection. That’s all I needed—I hadn’t even considered it, but it proved the perfect solution.

Here’s how simple it is (omitting try/catch and other code for clarity):

MyClass myClass = new MyClass();
Method m = myClass.getClass().getDeclaredMethod(“myMethod”, new Class[]{});
m.invoke(myClass, new Object[]{});

That’s it! The main points to remember are:

  • Use getDeclaredMethod(), not getMethod(). If myMethod() is private, calling getMethod() throws NoSuchMethodException.
  • setAccessible(true) bypasses Java’s access checking when the method is invoked. Skipping this step results in an IllegalAccessException.

If you’ve never used reflection before, it looks a little strange and it’s next to impossible to learn it from the Javadocs, but it’s an invaluable tool for your toolbox.

Explore posts in the same categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: