Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java test class with many private methods [duplicate]

I have a class that has the responsibility of importing contracts from a CSV to database.

The class itself has only one public method that starts the import and the other methods are all private (because only the class itself will use, and they hold the logic).

I'm starting to make tests for this class using Spock and there are many private methods, how should I test it?

Should I turn them into public to test? Test only the main method, the public one?

Whats the best?

like image 446
Kennedy Oliveira Avatar asked Jan 15 '15 17:01

Kennedy Oliveira


People also ask

Can we write test cases for private methods in Java?

In Java you can write tests itself in the class to be tested and your test methods should be able to call private methods as well.

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 you cover a private method in a test class?

Annotate the mehod with @testVisible: Use the TestVisible annotation to allow test methods to access private or protected members of another class outside the test class. These members include methods, member variables, and inner classes. This annotation enables a more permissive access level for running tests only.


2 Answers

You can use reflection to achieve this. The Method class has a method called setAcessible(boolean) which enables you to call it even if declared as private/protected/default. See the example below:

YourClass yourClassInstance = new YourClass();
Method yourMethod = YourClass.class.getDeclaredMethod("yourMethod", null);
yourMethod.setAccessible(true);
Object[] parameters = new Object[1];
parameters[0] = "A String parameter";
Object result = yourMethod.invoke(yourClassInstance, parameters);
like image 91
Bruno Marco Visioli Avatar answered Oct 13 '22 20:10

Bruno Marco Visioli


In theory, your private methods are being used ultimately by one of the public methods, or else they're not used at all. So typically you setup your tests to call the public methods with the necessary context so that it hits your private methods.

The unit tests are primarily testing the compilation unit (i.e. the class). You can unit test methods directly but then they have to be public, which goes against having a nice clean API.

So test your public method enough to hit all the private methods. Private methods are internal mechanics of the class, they don't need to be tested directly.

like image 32
mprivat Avatar answered Oct 13 '22 20:10

mprivat