javaunit-testingdatetime

Unit testing time-based logic in Java


I have a method which implements different logic on data fetched from a DB depending on what the current date is.

I want to test it by having the unit test create objects, save them in the DB and invoke the tested method. However, in order to have predictable results I need to change the system date each time and I don't know how to do that in Java.

Suggestions?


Solution

  • You can generate your expected results using the current date.

    Or you write your system to use a date/time you give it when being tested (rather than the clock) That way the time is always what the test expects.

    I use something like

    interface TimeSource {
        long currentTimeMS(); // actually I have currentTimeNS
        void currentTimeMS(long currentTimeMS);
    }
    
    enum VanillaTimeSource implements TimeSource {
        INSTANCE;
    
        @Override
        public long currentTimeMS() {
            return System.currentTimeMillis();
        }
    
        @Override
        public void currentTimeMS(long currentTimeMS) {
            // ignored
        }
    }
    
    class FixedTimeSource implements TimeSource {
        private long currentTimeMS;
        @Override
        public long currentTimeMS() {
            return currentTimeMS;
        }
    
        @Override
        public void currentTimeMS(long currentTimeMS) {
            this.currentTimeMS =              currentTimeMS;
        }
    }
    

    In tests I use a FixedTimeSource which can be data driven e.g. set by inputs/events. In production I use a VanillaTimeSource.INSTANCE which ignores times in inputs/events and uses the current time.