0

I'm using Instant.now() to get the current UTC millis, and then truncate it to the nearest hour. All my JUnit are failing because they are taking the current System time. How can I make Instant.now() return a fixed value which I could supply in the JUnit test.

public static Long getCurrentHour() {
    Instant now = Instant.now();
    Instant cH = now.truncatedTo(ChronoUnit.HOURS);
    return cH.toEpochMilli();
}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Novice User
  • 3,552
  • 6
  • 31
  • 56
  • Possible duplicate of [Writing and testing convenience methods using Java 8 Date/Time classes](https://stackoverflow.com/questions/52956373/writing-and-testing-convenience-methods-using-java-8-date-time-classes) – Ole V.V. Oct 21 '19 at 17:59
  • 1
    Not fully, that SO requires the source to have a `setClock` which is not good. – Novice User Oct 21 '19 at 18:05
  • 1
    I thought that the `setClock` *was* good. It makes the class testable. Mileages differ. – Ole V.V. Oct 21 '19 at 18:32

1 Answers1

0

You should mock the static method Instant.now() to give you a static instant value.
You can use PowerMockito for that.

@RunWith(PowerMockRunner.class)
@PrepareForTest(Instant.class)
public class TestClass {
    @Mock private Instant mockInstant;

    @Test
    public void getCurrentHour() throws Exception {
        PowerMockito.mockStatic(Instant.class);
        when(Instant.now()).thenReturn(mockInstant);
        when(mockInstant.truncatedTo(ChronoUnit.HOURS)).thenReturn(mockInstant);
        long expectedMillis = 999l;
        when(mockInstant.toEpochMilli()).thenReturn(expectedMillis);

        assertEquals(expectedMillis, YourClass.getCurrentHour());
    }
}
Nir Levy
  • 12,750
  • 3
  • 21
  • 38