javajava-8java-timesystemtime

How can I mock java.time.LocalDate.now()


In my test case, I need test time sensitive method, in that method we're using java 8 class LocalDate, it is not Joda.

What can I do to change time, when I'm running test


Solution

  • In your code, replace LocalDate.now() with LocalDate.now(clock);.

    You can then pass Clock.systemDefaultZone() for production and a fixed clock for testing.


    This is an example :

    First, inject the Clock. If you are using spring boot just do a :

    @Bean
    public Clock clock() {
        return Clock.systemDefaultZone();
    }
    

    Second, call LocalDate.now(clock) in your code :

    @Component
    public class SomeClass{
    
        @Autowired
        private Clock clock;
    
        public LocalDate someMethod(){
             return LocalDate.now(clock);
        }
    }
    

    Now, inside your unit test class :

    // Some fixed date to make your tests
    private final static LocalDate LOCAL_DATE = LocalDate.of(1989, 01, 13);
    
    // mock your tested class
    @InjectMocks
    private SomeClass someClass;
    
    //Mock your clock bean
    @Mock
    private Clock clock;
    
    //field that will contain the fixed clock
    private Clock fixedClock;
    
    
    @Before
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    
        //tell your tests to return the specified LOCAL_DATE when calling LocalDate.now(clock)
        fixedClock = Clock.fixed(LOCAL_DATE.atStartOfDay(ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault());
        doReturn(fixedClock.instant()).when(clock).instant();
        doReturn(fixedClock.getZone()).when(clock).getZone();
    }
    
    @Test
    public void testSomeMethod(){
        // call the method to test
        LocalDate returnedLocalDate = someClass.someMethod();
    
        //assert
        assertEquals(LOCAL_DATE, returnedLocalDate);
    }