我发现处理时间紧迫的代码最可靠的方法是将所有时间紧迫的函数包装在自己的类中。我通常称之为
TimeHelper。因此,此类可能如下所示。
import java.util.Date;public class TimeHelper{ public long currentTimeMillis(){ return System.currentTimeMillis(); } public Date makeDate(){ return new Date(); }}并且可能有更多相同类型的方法。现在,任何使用此类函数的类都应具有(至少)两个构造函数-您将在应用程序中使用的普通构造函数,以及一个以a
TimeHelper为参数的私有程序包。这
TimeHelper需要存放起来以备后用。
public class ClassThatDoesStuff { private ThingConnector connector; private TimeHelper timeHelper; public ClassThatDoesStuff(ThingConnector connector) { this(connector, new TimeHelper()); } ClassThatDoesStuff(ThingConnector connector, TimeHelper timeHelper) { this.connector = connector; this.timeHelper = timeHelper; } }现在,在您的班级中,不要编写
System.currentTimeMillis(),而是编写
timeHelper.currentTimeMillis()。当然,这将具有完全相同的效果。除了现在,您的课程变得更加可测试了。
测试课程时,请模拟
TimeHelper。配置此模拟(使用Mockito的
when和
thenReturn,或者使用
doReturn),以返回您喜欢的任何时间值-
测试所需的任何值。如果要
currentTimeMillis()在测试过程中多次调用,则甚至可以在此处返回多个值。
现在,使用第二个构造函数制作要测试的对象,然后传递模拟。这使您可以完美控制测试中将使用什么时间值。并且您可以使您的断言或验证断言恰好使用了正确的值。
public class ClassThatDoesStuffTest{ @Mock private TimeHelper mockTime; @Mock private ThingConnector mockConnector; private ClassThatDoesStuff toTest; @Test public void doesSomething(){ // Arrange initMocks(this); when(mockTime.currentTimeMillis()).thenReturn(1000L, 2000L, 5000L); toTest = new ClassThatDoesStuff(mockConnector, mockTime); // Act toTest.doSomething(); // Assert // ... ??? }}如果这样做,您将知道测试将始终有效,并且永远不会依赖于操作系统的时间划分策略。您还可以验证时间戳的确切值,而不必断言它们落在某个近似间隔内。



