Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test local inner class methods in java? [duplicate]

Tags:

In many application I often have algorithms which make use of dedicated sub-algorithms (or simply well defined pieces of code).

Till now, when I wrote the main algorithm, i created a private method for each sub-algorithm like in the example below (OldStyle):

public class OldStyle {      public int mainAlg() {         int x = subAlg01();         int y = subAlg02();         int z = x * y;         return z;     }      private int subAlg01() {         return 3;     }      private int subAlg02() {         return 5;     } } 

This worked fine but I didn't like having a proliferation of methods (subAlg01 and subAlg02) which, even if private, were only used by one method (mainAlg).

Recently I dicovered the use of local inner classes and now my example is (NewStyle):

public class NewStyle {      public int mainAlg() {         class Nested {              public int subAlg01() {                 return 3;             }              public int subAlg02() {                 return 5;             }         }         Nested n = new Nested();         int x = n.subAlg01();         int y = n.subAlg02();         int z = x * y;         return z;     } } 

I like it very much but now I have the following problem: how do I test subAlg01 and subAlg02 using JUnit?

By the way: I'm using eclipse.

Thanks for you help.

Edit: I try to explain better: I have, let's say, a sorting algorithm and I want to test it to be sure it runs as expected. This sorting algorithms is used by only method m of class X. I could make it a private method of class X but class X usually has nothing to do with sorting, so why "spoil" class X with the sorting method? So I put it inside method m. Some time later I want to improve my sorting algorithm (I make it faster) but I want to be sure that it's behavior is as expected, so I want to re-test it with the original tests.

That's what I want to do, maybe there is no solution, I hope someone may help me.

Edit after answer choice. I selected Rodney answer because his solution is the one I adopted: a standalone helper class helps me (it's a helper!) to have a clear view of what are the sub methods and it also gives me the ability to test them.

like image 319
Filippo Tabusso Avatar asked Jul 28 '10 13:07

Filippo Tabusso


People also ask

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.

How do you access a local inner class method?

You just need to write a class within a class. Unlike a class, an inner class can be private and once you declare an inner class private, it cannot be accessed from an object outside the class. Following is the program to create an inner class and access it.

How do you call an inner class method?

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax: OuterClass. InnerClass innerObject = outerObject.

Can inner classes be reused?

Regular inner class holds reference to object of outer class, so its instance cannot be created without outer class. It means that inner classes cannot be re-used from outside the outer class. Anonymous inner classes you are using cannot be reused for sure: they are created in context of outer method.


2 Answers

You should only test the public interface of classes, not private members or private inner classes. Private members are meant to be implementation details, used only by public methods of the class (directly or indirectly). So you can unit test these indirectly via their caller methods. If you feel you don't have enough granularity in those unit tests, or that you can't sense (some of) the results you are interested in, this probably signs a problem with your design: the class may be too big, trying to do too much, thus some of its functionality may need to be extracted into a separate class, where it can then be unit tested directly.

In the current example, if the inner class itself contains a lot of code, you may simply turn it into a top-level class, then you can unit test its methods directly.

(Btw your inner class should be static if it doesn't need to refer to the enclosing class instance.)

like image 168
Péter Török Avatar answered Oct 21 '22 07:10

Péter Török


Filippo, I understand your frustration with the problem and with some of the answers. When I first started using JUnit many years ago, I too wanted to test private code, and I thought it silly of the gurus to say it was a bad idea.

Turns out they were right (surprise!) but only after writing quite a few tests did I understand why. You might need to go through the same process, but you will eventually come to the same conclusion ;-)

Anyway, in your situation, I would make Nested into a proper standalone class, possibly in a separate package to make obvious that it's a helper classes. Then I would write tests for it directly, independent of any other tests.

Then I'd write tests for NewStyle and focus only on the behaviour of NewStyle.

(Quite probably I would also inject Nested into NewStyle rather than instantiating it within NewStyle -- i.e. make it an argument to NewStyle's constructor.

Then when I write tests for NewStyle in the test I'd pass in an instance of Nested and carry on. If I felt particularly tricky, I'd create an interface out of Nested and create a second implementation, and test NewStyle with that, too.)

like image 41
Rodney Gitzel Avatar answered Oct 21 '22 08:10

Rodney Gitzel