编程语言
首页 > 编程语言> > 使用Java 8 Clock对类进行单元测试

使用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