Rookie
Rookie

Reputation: 5467

Unit test private inner class methods

I have a Class A which has an internal Cache represented by a Class B. this inner class is private since the cache need not be visible to external consumers and is only to assist the outer class A. I am using Jmock and Java

public class A {
    ...
    private class B {
    ... 
       public void testMethod() {
          //The method I want to unit test
          ...
       }
    }
}

This is shown above. I am not sure how to unit test the testMethod() which is from private inner class B (as class B is not visible to the outer world).

Please advise!

Thanks!

Upvotes: 6

Views: 16955

Answers (4)

weston
weston

Reputation: 54781

If you are strictly following a TDD approach, private methods and private inner classes are only the result of the refactoring step in the red/green/refactor cycle.

So the approach should be:

  1. Write tests that test the public interface of the class including this caching behavior and write code to pass these tests as you go. This will result in long public methods and some fields that are clearly only related to caching.
  2. Then refactor out some cache related private methods from the long public methods.
  3. Next step should be to move the private cache fields and methods to private inner class. After each refactoring, the tests should pass without modification.

You'll finish with privates methods that are fully tested still, but only via the public interface.

Upvotes: 5

Jano Janahan
Jano Janahan

Reputation: 101

As said above, you should rethink why you are testing a private method, and I will not go into that any more, as others have given some good information.

However, if there is a need to still test a private method, use reflection to "unlock" the private method, and use Apache Commons to avoid having to write common code (DRY - Don't Repeat Yourself) https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/reflect/package-summary.html

If you need to mock a private method, for example a DB call that is done in a private method of a class. Again the best way is to redesign it so the DB component is abstracted out, but if you HAVE to do it, consider PowerMock

https://code.google.com/p/powermock/wiki/MockPrivate

Upvotes: 1

KDP
KDP

Reputation: 1481

Unit testing private methods/classes is not recommended.It is suffice to test the parent method which calls the private methods.Having said that,you can assert / validate the effects of the private class.

for example,

if your inner class is changing some value in database,you can call the parent method and can assert against the db values.This make sure that your private methods/private inner classes get tested.

refer : unit testing private methods

Upvotes: 3

David
David

Reputation: 218837

since the cache need not be visible to external consumers

A unit test is an external consumer. It's a class which invokes functionality on the object being tested, just like any other class.

Caveat: There is much opinion and debate on this matter. What I'm presenting here isn't "the one true answer" but is based on my own experience in maintaining unit tests in code.

Don't directly unit test private members. Not only does it generally take a little bit of trickery to make that happen, it creates coupling between the classes. (The test class and the class being tested.) Exposing the internals and coupling to them is a violation of object oriented principles.

Rather than thinking of your tests in terms of the methods you call on the class, think of your tests in terms of the functionality you invoke on the unit. Whatever functionality that unit exposes is what should be tested.

This leads to a few conclusions:

  • If there is no public functionality which internally invokes the private members in question, then why are those private members there at all? Just remove them.
  • If the private functionality is very complex and very difficult to invoke/validate using only public functionality then perhaps some refactoring is in order to simplify the class.

Since code which uses the object can only invoke the public functionality, code which tests the object should only validate the public functionality.

Upvotes: 9

Related Questions