K
K
KaminskyIlya2015-01-23 15:33:00
Software testing
KaminskyIlya, 2015-01-23 15:33:00

How to test private methods of a class?

There is a certain class, and the work of its public methods is based on the work of private auxiliary methods. Well let it be like this:

public class PersonDate
{
public PersonDate(Date birthday) { ... }

public int getYearsOld() 
{
  return isValid() ? getYear( getNextBirthdayDate() ) - getYear( getBornDate() ) + 1 : 0; 
}
// (TODO: нужен тест) возвращает год для даты
private static int getYear( Date date ) { ... }
// (TODO: нужен тест) возвращает дату следующего дня рождения
private Date getNextBirthdayDate() { ... }

You need to make sure that the private helper functions getYear() and getNextBirthdayDate() work correctly. Actually, how to test their work in JUnit or any other similar framework?
You can, of course, say that unit testing (according to Feng Shui) does not imply knowledge of the internal structure of the class being tested, and limit yourself to testing only external methods (considering the class purely as a black box). However, let's leave aside the "ideological wars" and concentrate on the task at hand. I see the following ways to solve the issue.
1. Method one.
The getYear() method is declared static. It can be moved to a public helper class, either internal or external:
static final class DateUtils
{
public static int getYear( Date date ) { ... }
}

and write a test for the new class. In this case it will help. Moreover, according to the rules of good code, putting logic that does not require class data into an isolated function is even correct. But what to do when such a method is not static and its work is based on the value of the internal fields of the class?
2. Method two.
Declare the method under test with package access level. This will work, because the testing class is compiled with the class under test in the same package. But to change the scope only for the sake of writing a test... hmm...
3. The third way. Long forgotten old.
Write a testing class inside the one under test:
public class PersonDate
{
...
public static class PersonDateTest
{
    @Test
    public testGetNextBirthDate()
    {
    }
}

In this case, the testing class gets full access to all the private fields of the owning object.
But it seems like such an approach is no longer in the mainstream? It seems that earlier (before JUnit and similar frameworks), this was the main method of writing tests. When compiling, internal test classes turn into separate files of the form PersonDate$PersonDateTest.class and can then be easily removed from production by assembly tools.
Colleagues, maybe someone knows other more beautiful ways?
Or do some frameworks provide similar functionality?
I will be grateful for all your answers.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Artem, 2015-01-23
@KaminskyIlya

Colleagues, maybe someone knows other more beautiful ways?
- through reflection! If you have the ability to change the scope, then you should not use it. If this is not possible, then here is a pattern for you:
Method method = PersonDate.class.getDeclaredMethod("getYear", Int.class);
        method.setAccessible(true);
        method.invoke(targetObject, argObjects);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question