LocalDateTime.of returns null



我正在尝试将使用java.time.LocalDateTime的测试代码单位。我能够使模拟工作,但是当我添加时间(分钟或几天)时,我最终会获得null值。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ LocalDateTime.class })
public class LocalDateTimeMockTest
{
    @Test
    public void shouldCorrectlyCalculateTimeout()
    {
        // arrange
        PowerMockito.mockStatic(LocalDateTime.class);
        LocalDateTime fixedPointInTime = LocalDateTime.of(2017, 9, 11, 21, 28, 47);
        BDDMockito.given(LocalDateTime.now()).willReturn(fixedPointInTime);
        // act
        LocalDateTime fixedTomorrow = LocalDateTime.now().plusDays(1); //shouldn't this have a NPE?
        // assert
        Assert.assertTrue(LocalDateTime.now() == fixedPointInTime); //Edit - both are Null
        Assert.assertNotNull(fixedTomorrow); //Test fails here
        Assert.assertEquals(12, fixedTomorrow.getDayOfMonth());
    }
}

我理解(我想我愿意)LocalDateTime是不变的,我认为我应该得到一个新实例而不是null值。

事实证明,是.of方法给我一个null值。为什么?

根据文档:

使用PowerMock.mockStatic(ClassThatContainsStaticMethod.class)进行模拟所有此类的方法。

和:

请注意,即使该类是最终的,您也可以在类中模拟静态方法。该方法也可以是最终的。仅模拟类的特定静态方法,请参阅文档中的部分模拟部分

要在系统类中模拟静态方法,您需要遵循此方法。

您告诉它要模拟所有静态方法,但没有为of()方法提供模拟。

解决方案:为of()方法添加模拟,或更改以使用部分模拟,因此未模拟of()方法。

基本上,读取并按照文档的说明

@andreas'正确解释了有关PowerMock用法的解释(您还在自己的答案中弄清楚)。

我只想添加另一种方法。为了测试当前日期/时间,您可以使用java.time.Clock。使用此类,您可以创建一个固定时钟(Clock总是返回相同的当前日期/时间)并在测试中使用它。

这样,就无需模拟静态方法(我必须删除测试类中的PowerMock注释)。唯一的区别是时钟必须传递到now()方法:

@Test
public void shouldCorrectlyCalculateTimeout() {
    // create a clock that always returns the same current date/time
    LocalDateTime fixedPointInTime = LocalDateTime.of(2017, 9, 11, 21, 28, 47);
    ZoneId zone = ZoneId.systemDefault();
    Clock clock = Clock.fixed(fixedPointInTime.atZone(zone).toInstant(), zone);
    // use the clock in now() method
    LocalDateTime fixedTomorrow = LocalDateTime.now(clock).plusDays(1);
    // assert (use equals() instead of == because it doesn't return the same instance)
    Assert.assertTrue(LocalDateTime.now(clock).equals(fixedPointInTime));
    Assert.assertNotNull(fixedTomorrow);
    Assert.assertEquals(12, fixedTomorrow.getDayOfMonth());
}

我必须使用equals()方法(而不是==)来比较日期,因为now(clock)创建了一个新实例,尽管所有实例都将与同一日期/时间相对应(这就是重要的,IMO)。

>

ps:在上面的代码中,我正在使用JVM默认时区(ZoneId.systemDefault())。唯一的问题是,即使在运行时,也可以在不通知的情况下进行更改,因此最好始终将其明确显示。

在此特定代码中,时区部分被忽略,因此您可以使用任何区域,这不会有太大的不同 - 除非您在发生日光节省时间转换时得到了时区和本地日期的组合,否则会产生意外的结果。

如果您不想依靠它,则可以替换ZoneId.systemDefault()并改用ZoneOffset.UTC(UTC没有任何日光节省效果)。在这种情况下,您可以这样创建时钟:

ZoneOffset utc = ZoneOffset.UTC;
Clock clock = Clock.fixed(fixedPointInTime.toInstant(utc), utc);

,因此powermockito.mockstatic与下一行代码混乱。只需将固定点的实例化以在模型之类之前执行。...

在类中创建一个方法

public class SomeClass{
    public static void main(String[] args) {
        LocalDateTime now = getCurrentLocalDateTime(); 
        System.out.println(now);
    }
    private LocalDateTime getCurrentLocalDateTime() {
        return LocalDateTime.now();
    }
}

,在Test类中,您使用:

@PrepareForTest(SomeClass.class)
@RunWith(PowerMockRunner.class)

在测试柜中:

LocalDateTime tommorow= LocalDateTime.now().plusDays(1);
SomeClass classUnderTest = PowerMockito.spy(new SomeClass());
PowerMockito.when(classUnderTest, "getCurrentLocalDateTime").thenReturn(tommorow);

相关内容

  • 没有找到相关文章

最新更新