Is it safe to use DateTimeUtils.setCurrentMillisFixed in tests?

无人久伴 提交于 2019-12-05 00:06:23

You must ensure that DateTimeUtils.setCurrentMillisSystem() is invoked in the tearDown method. So that one test does not affect another. TestNG should invoke tearDown even if an exception occurs in your test.

I often prefer another way when I want to decouple a class from System.currentTimeMillis();. I introduce an interface Clock and one implementation SystemClock like this:

public interface Clock {
    public long getCurrentTimeMillis();
}

public class SystemClock implements Clock {
    public long getCurrentTimeMillis(){
        return System.currentTimeMillis();
    }
}

For the tests it is then easy to create a mock that either returns a fixed time on every invocation or a series of predefined times.

Some might argue that it is overengineering to introduce such an interface to decouple only one method and it would be a performance impact. But fortunately we have a JIT compiler and since JIT knows that only the SystemClock class is loaded it knows that no other implementation exist (at the moment). At this assumption it can just use inline method.

So I prefer to write code in the way it can be tested best.

EDIT

With Java 8 you might want to use the Supplier<Long> interface.

E.g. in your client code you can than use method references

public class SomeClass {
    private Supplier<Long> currentTimeMillisSupplier;

    public SomeClass(){
         this(System::currentTimeMillis);
    }

    SomeClass(Supplier<Long> currentTimeMillisSupplier){
        this.currentTimeMillisSupplier = currentTimeMillisSupplier;
    }
}

The default constructor is for 'normal' use, while the other package scoped constructor can be used for unit tests. Just place the test class in the same package.

You can also use the Clock interface, because it is a @FunctionalInterface.

public class SomeClass {
    private Clock clock;

    public SomeClass(){
         this(System::currentTimeMillis);
    }

    public SomeClass(Clock clock){
        this.clock = clock;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!