如何使用PowerMock模拟LocalDate.now()

时间:2017-08-09 13:21:09

标签: java mockito powermock java-time

我想使用PowerMock仅模拟now() LocalDate。它似乎忽略了thenReturn值:

java.lang.AssertionError: 
Expected :2008
Actual   :2017

测试设置:

@PrepareForTest(LocalDate.class)
@RunWith(PowerMockRunner.class)
public class UserTest {

    @Test
    public void nowShouldReturnSameYear() throws Exception {
        LocalDate expected = LocalDate.parse("2008-04-04");

        PowerMockito.spy(LocalDate.class);
        when(LocalDate.now()).thenReturn(parse);

        Foo foo = new Foo();
        assertEquals(expected.getYear(), foo.getRightNow().getYear());
    }

Foo.java

public LocalDate getRightNow(){
        final LocalDate rightNow = LocalDate.now();
        return rightNow;
    }

1 个答案:

答案 0 :(得分:6)

您应该PrepareForTest Foo班级:

@PrepareForTest(Foo.class)
@RunWith(PowerMockRunner.class)
public class ...

我不确定spy对静态方法的行为如何,所以我更喜欢使用mockStatic

PowerMockito.mockStatic(LocalDate.class);
when(LocalDate.now())....

为了使代码更易于测试并且不依赖于模拟静态方法,您还可以重构代码以使用java.time.Clock

public class Foo {

    private Clock clock;

    public Foo() {
        // use the system's default clock
        this(Clock.systemDefaultZone());
    }

    public Foo(Clock clock) {
        // use a custom clock
        this.clock = clock;
    }

    public LocalDate getRightNow() {
        final LocalDate rightNow = LocalDate.now(this.clock);
        return rightNow;
    }
}

如果你没有指定Clock,它将使用系统的默认值(正好是now()方法在没有参数的情况下调用的方式。)

然后,在测试中,您创建一个始终返回相同日期并将其传递给Clock类的Foo。在这种情况下,您将不需要所有PowerMockito内容:

public class UserTest {

    @Test
    public void nowShouldReturnSameYear() throws Exception {
        LocalDate parse = LocalDate.parse("2008-04-04");
        // create a fixed clock (it always return the same date, using the system's default timezone)
        ZoneId zone = ZoneId.systemDefault();
        Clock clock = Clock.fixed(parse.atStartOfDay(zone).toInstant(), zone);

        Foo foo = new Foo(clock);
        assertEquals(parse.getYear(), foo.getRightNow().getYear());
    }
}