问题描述
Java 8引入了 java.time.Clock
,它可以用作许多其他 java.time
的参数对象,允许您向其中注入真实或假的时钟。例如,我知道您可以创建 Clock.fixed()
然后调用 Instant.now(时钟)
并且它将返回您提供的固定 Instant
。这听起来非常适合单元测试!
Java 8 introduced java.time.Clock
which can be used as an argument to many other java.time
objects, allowing you to inject a real or fake clock into them. For example, I know you can create a Clock.fixed()
and then call Instant.now(clock)
and it will return the fixed Instant
you provided. This sounds perfect for unit testing!
然而,我无法弄清楚如何最好地使用它。我有一个类,类似于以下内容:
However, I'm having trouble figuring out how best to use this. I have a class, similar to the following:
public class MyClass {
private Clock clock = Clock.systemUTC();
public void method1() {
Instant now = Instant.now(clock);
// Do something with 'now'
}
}
现在,我想对这段代码进行单元测试。我需要能够设置 clock
来产生固定时间,以便我可以在不同时间测试 method()
。显然,我可以使用反射将时钟
成员设置为特定值,但如果我不必求助于反射,那就太好了。我可以创建一个公共 setClock()
方法,但这感觉不对。我不想在方法中添加 Clock
参数,因为实际代码不应该考虑传入时钟。
Now, I want to unit test this code. I need to be able to set clock
to produce fixed times so that I can test method()
at different times. Clearly, I could use reflection to set the clock
member to specific values, but it would be nice if I didn't have to resort to reflection. I could create a public setClock()
method, but that feels wrong. I don't want to add a Clock
argument to the method because the real code shouldn't be concerned with passing in a clock.
处理此问题的最佳方法是什么?这是新代码,所以我可以重新组织这个类。
What is the best approach for handling this? This is new code so I could reorganize the class.
编辑:为了澄清,我需要能够构建一个 MyClass
object但是能够让那个对象看到两个不同的时钟值(好像它是一个常规的系统时钟)。因此,我无法将固定时钟传递给构造函数。
To clarify, I need to be able to construct a single MyClass
object but be able to have that one object see two different clock values (as if it were a regular system clock ticking along). As such, I cannot pass a fixed clock into the constructor.
推荐答案
让我把Jon Skeet的答案和注释放入代码中:
Let me put Jon Skeet's answer and the comments into code:
正在测试的课程:
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 8 Clock对类进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!