Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 878
Rookie Avatar asked Jun 28 '15 14:06

Rookie


People also ask

Can we test private methods in unit testing?

Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods aren't aware of. Furthermore, changing our implementation details shouldn't lead us to change our tests.

How do I test a private function or a class that has private methods?

To test private methods, you just need to test the public methods that call them. Call your public method and make assertions about the result or the state of the object. If the tests pass, you know your private methods are working correctly.

How does JUnit test inner class methods?

First, we have to add a new inner class called A to our test class and annotate the inner class with the @Nested annotation. After we have created the A class, we have to add one setup, teardown, and test method to the created inner class.


3 Answers

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.

like image 165
David Avatar answered Oct 21 '22 13:10

David


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.

like image 23
weston Avatar answered Oct 21 '22 15:10

weston


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

like image 25
KDP Avatar answered Oct 21 '22 14:10

KDP