2

I have a method like below ,

public static boolean isBetweenMonthDays(int startDayOfMonth,
        int endDayOfMonth) {

    LocalDate today = LocalDate.now();

    if (today.getDayOfMonth() >= startDayOfMonth
        && today.getDayOfMonth() <= endDayOfMonth) {
        return true;
    }

    return false;
    }

This is a simple method in utility class but there are many other complicated methods too and result is dependent on today's date so my asserts will fail on certain dates.

What is preferred to unit test such methods?

UPDATE: are these below kind of unit tests considered bad practice since most are advising in injecting LocalDate dependency & making class testable?

I am hesitant in doing that since its a static utility class and clients work only on integers?

@Test
    public void testIsBetweenMonthDays_success_true() {

    LocalDate today = LocalDate.now();

    boolean result = ResponseMatchingUtil.isBetweenMonthDays(10, 25);

    if (today.getDayOfMonth() >= 10 && today.getDayOfMonth() <= 25)
        assertTrue(result);
    else
        assertFalse(result);

    }

    @Test
    public void testIsBetweenMonthDays_success_false() {

    LocalDate today = LocalDate.now();

    boolean result = ResponseMatchingUtil.isBetweenMonthDays(4, 10);

    if (today.getDayOfMonth() >= 4 && today.getDayOfMonth() <= 10)
        assertTrue(result);
    else
        assertFalse(result);

    }
Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
  • I'd say you should mock the dates. – Flown Jun 20 '17 at 09:33
  • Remove the dependency on the current date: inject `today`. – Andy Turner Jun 20 '17 at 09:35
  • 3
    Related: [Mocking time in Java 8's java.time API](https://stackoverflow.com/questions/24491260/mocking-time-in-java-8s-java-time-api) – Jesper Jun 20 '17 at 09:36
  • @AndyTurner: This is a kind of utility class with static utility methods. – Sabir Khan Jun 20 '17 at 09:46
  • @SabirKhan that's totally irrelevant to its testability. Somehow you need to be able to get dates, times etc which you can control, and you do that by injecting the source of those dates, times etc. Note that by "inject" I don't mean "use a dependency injection framework" (necessarily): I mean pass the `LocalDate` as a parameter to the method. – Andy Turner Jun 20 '17 at 09:47
  • Don’t write `if(condition) return true; [else] return false;` Just write `return condition;`. Likewise, don’t write `if(b) assertTrue(a); else assertFalse(a);` Just write `assertEquals(b, a);`. Besides that, you seem to have an interesting idea of what are “complicated methods”… – Holger Jun 20 '17 at 10:04
  • @Holger : Thanks for catching that, I have edited question. That is a simple method but other methods are more complicated than that. – Sabir Khan Jun 20 '17 at 10:20

1 Answers1

1

Refactor it so it becomes testable:

public static boolean isBetweenMonthDays(int startDayOfMonth,
        int endDayOfMonth, LocalDate date) {

    if (date.getDayOfMonth() >= startDayOfMonth
        && date.getDayOfMonth() <= endDayOfMonth) {
        return true;
    }

    return false;
    }

public static boolean isBetweenMonthDays(int startDayOfMonth,
        int endDayOfMonth) {

    return isBetweenMonthDays(startDayOfMonth, endDayOfMonth, LocalDate.now());
    }
kerner1000
  • 3,382
  • 1
  • 37
  • 57
  • so clients use `isBetweenMonthDays(int startDayOfMonth, int endDayOfMonth)` & I unit test `isBetweenMonthDays(int startDayOfMonth,int endDayOfMonth, LocalDate date)` ? – Sabir Khan Jun 20 '17 at 09:57
  • Exactly. The two parameter method you do not need to test, since it delegates only to the three parameter method, using `LocalDate.now` as the third parameter. – kerner1000 Jun 20 '17 at 10:04
  • I will make only one modification - that will make accessibility of testable method to be `protected` instead of `public` . This approach does have a down side in terms of code coverage. – Sabir Khan Jun 20 '17 at 10:36