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 methodsclock.instant()
is mocked to return the desired valueClock.systemUTC()
is static so we need mockStatic- using
@Before
/@After
is required to close MockedStatic (alternatively you can usetry(MockedStatic<Clock> clockMock = mockStatic(Clock.class)) {...}
)