使用Java 8 Clock对类进行单元测试
作者:互联网
Java 8引入了java.time.Clock,它可以用作许多其他java.time对象的参数,允许您向它们注入真实或假的时钟.例如,我知道您可以创建一个Clock.fixed(),然后调用Instant.now(时钟),它将返回您提供的固定Instant.这听起来非常适合单元测试!
但是,我无法弄清楚如何最好地使用它.我有一个类,类似于以下内容:
public class MyClass {
private Clock clock = Clock.systemUTC();
public void method1() {
Instant now = Instant.now(clock);
// Do something with 'now'
}
}
现在,我想对这段代码进行单元测试.我需要能够设置时钟以产生固定的时间,以便我可以在不同的时间测试method().很明显,我可以使用反射将时钟成员设置为特定值,但如果我不必使用反射就会很好.我可以创建一个公共setClock()方法,但这感觉不对.我不想在方法中添加Clock参数,因为真正的代码不应该考虑传入时钟.
处理此问题的最佳方法是什么?这是新代码,所以我可以重新组织这个类.
编辑:为了澄清,我需要能够构造一个MyClass对象,但能够让一个对象看到两个不同的时钟值(就好像它是一个常规的系统时钟一样).因此,我无法将固定时钟传递给构造函数.
解决方法:
让我把Jon Skeet的答案和评论放到代码中:
被测试的班级:
public class Foo {
private final Clock clock;
public Foo(Clock clock) {
this.clock = clock;
}
public void someMethod() {
Instant now = clock.instant(); // this is changed to make test easier
System.out.println(now); // Do something with 'now'
}
}
单元测试:
public class FooTest() {
private Foo foo;
private Clock mock;
@Before
public void setUp() {
mock = mock(Clock.class);
foo = new Foo(mock);
}
@Test
public void ensureDifferentValuesWhenMockIsCalled() {
Instant first = Instant.now(); // e.g. 12:00:00
Instant second = first.plusSeconds(1); // 12:00:01
Instant thirdAndAfter = second.plusSeconds(1); // 12:00:02
when(mock.instant()).thenReturn(first, second, thirdAndAfter);
foo.someMethod(); // string of first
foo.someMethod(); // string of second
foo.someMethod(); // string of thirdAndAfter
foo.someMethod(); // string of thirdAndAfter
}
}
标签:java,java-8,unit-testing,java-time 来源: https://codeday.me/bug/20190917/1809901.html