Mock Instant.now() without using Clock into Constructor or without Clock Object

Mockito based solution where code uses plain Instant.now()

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import java.time.Clock;
import java.time.Instant;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

public class MockInstantTest {

  private MockedStatic<Clock> clockMock;

  @BeforeEach
  public void setup() {
    mockInstant(1640000000); // set desired return value 2021-12-20T11:33:20Z
  }

  @AfterEach
  public void destroy() {
    clockMock.close();
  }

  private void mockInstant(long expected) {
    Clock spyClock = spy(Clock.class);
    clockMock = mockStatic(Clock.class);
    clockMock.when(Clock::systemUTC).thenReturn(spyClock);
    when(spyClock.instant()).thenReturn(Instant.ofEpochSecond(expected));
  }

  @Test
  void testWithMockedIstant() {
    // invoking Instant.now() will always return the same value
    assertThat(Instant.now().toString()).isEqualTo("2021-12-20T11:33:20Z");
  }
}

Solution Explained

Solution relays on the fact that Instant.now() invokes Clock.systemUTC().instant()

  • Clock is abstract so we spy for non static methods
  • clock.instant() is mocked to return the desired value
  • Clock.systemUTC() is static so we need mockStatic
  • using @Before/@After is required to close MockedStatic (alternatively you can use try(MockedStatic<Clock> clockMock = mockStatic(Clock.class)) {...})

Leave a Comment