0

I'm taking a stab at setting up unit tests for some utility classes in a project I'm working on, and one of the classes has a method that does some determination based on the current time.

public String firstDay() {
    Date dateDuJour = new Date();
    int jourCourant = dateDuJour.getDate();
    if (jourCourant == 1)
        return "firstDay";
    else
        return "otherDay";
}

How can I solve the problem of unit test a method that is used, the term new Date ()?

Edit

I would not modify working code in order to get a better Cobertura result, or to make sure something can pass a unit test.

Dali
  • 135
  • 2
  • 13
  • Just my two cents: I would not modify working code in order to get a better Cobertura result, or to make sure something can pass a unit test. Unit testing is a tool for us to take benefits out of it, not the opposite, and we should not get confused about it to the point as the guy in the link does (that DateTime class in the answer is a design aberration) – Jorge_B May 26 '14 at 16:43

3 Answers3

1

I would not modify working code in order to get a better Cobertura result, or to make sure something can pass a unit test.

It is ok to modify even working code to make it more easily testable. Dependency Injection pattern addresses scenarios like this. The basic idea is simple: Dependencies are passed on from dependent objects to the object that provides the service.

Gowtham
  • 1,465
  • 1
  • 15
  • 26
0

For better testability pass the Date-object as parameter instead of calling new Date() inside:

public String firstDay(Date dateDuJour) {
    int jourCourant = dateDuJour.getDate();
    if (jourCourant == 1)
        return "firstDay";
    else
        return "otherDay";
}

Your call will change from firstDay() to firstDay(new Date()).

After you change your code, you can easily pass mocked Date-Objects which test the possible cases.

Chrisport
  • 2,936
  • 3
  • 15
  • 19
  • just to simplify the code I showed you the firstDay method but in the real case I have the following method public void maMethode() { // some code Date dateDuJour = new Date(); int jourCourant = dateDuJour.getDate(); if (jourCourant == 1) { // some code } else { // some code } // some code } thx – Dali May 26 '14 at 16:54
  • The solution stays same, inject the dependency as parameter. You could wrap "new Date()" in a factory that can be passed in the constructor or via a init-method, then you can leave this method without parameter. Or you write a second method as Raffaele suggested. – Chrisport May 26 '14 at 19:46
0

I don't think that if statements should be unit tested. Anyway, as long as you use new Date() your code won't be testable, because the test result will depend on the day of the week the test is run. (Also, you should not use the deprecated Date.getDate()).

I'd split your method into three methods:

private void doSomeAction(Date date) {
  Calendar cal = Calendar.getInstance();
  cal.setTime(date);
  if (cal.get(Calendar.DAY_OF_MONTH) == 1) {
    doSomeActionForFirstDay();
  } else {
    doSomeActionForOtherDays();
  }
}

public void doSomeActionForFirstDay() {
  // IMPLEMENT AND TEST THIS ONE
}

public void doSomeActionForOtherDays() {
  // IMPLEMENT AND TEST THIS ONE
}

and test only the second and third method. If you happen to use the idiom doSomeAction(new Date()) a lot in your code, you can always add a fourth method:

public void doSomeActionToday() {
  doSomeAction(new Date());
}

and this obviously doesn't need any test.

(Or you can look at these ways to manipulate the time read from System.currentTimeMillis())

Community
  • 1
  • 1
Raffaele
  • 20,627
  • 6
  • 47
  • 86
  • Good idea for refactoring codes but usually the utils methods are declared private. – Dali May 27 '14 at 08:08