【问题标题】:Java PowerMockito Mocking Instant.now()Java PowerMockito 模拟 Instant.now()
【发布时间】:2016-06-02 15:39:48
【问题描述】:

我正在尝试模拟静态方法 Instant.now(),并且在尝试模拟 java.time 包中的类时,我继续遇到奇怪的行为。请在下面查看我的代码以尝试模拟 Instant.now()

@RunWith(PowerMockRunner.class)
@PrepareForTest(Instant.class)
public class UnitTestClasss {
    @Test
    public void unitTestMethod() throws Exception {
        mockCurrentTimeAtMidNight();
        instanceOfSystemUnderTest.someMethodDependingOnTime();
        assertHandledHere();
    }

    /*See First Error Below */
    private void mockCurrentTimeAtMidNight() {
        ZonedDateTime current = ZonedDateTime.now();
        ZonedDateTime mockMidNight = ZonedDateTime.of(current.getYear(), current.getMonthValue(),
                current.getDayOfMonth(), 0, 0, 0, 0,current.getZone());

        PowerMockito.mockStatic(Instant.class);
        PowerMockito.when(Instant.now()).thenReturn(Instant.from(mockMidNight));
    }

    /*See Second Error Below */
    private void mockCurrentTimeAtMidNight2() {
        Calendar cal = Calendar.getInstance();

        ZonedDateTime mockMidNight = ZonedDateTime.of(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH),
                cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0, 0,ZoneId.of("US/Eastern"));
        Instant instant = mockMidNight.toInstant();
        PowerMockito.mockStatic(Instant.class);
        PowerMockito.when(Instant.now()).thenReturn(instant);
    }

}

错误 1 org.mockito.exceptions.misusing.UnfinishedStubbingException: 此处检测到未完成的存根: -> 在 org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

错误 2:原因:[源错误]toInstant() 未在 java.time.ZonedDateTime

【问题讨论】:

标签: java unit-testing mockito powermock


【解决方案1】:

据我所知,我收到了错误,因为最初我在单元测试中调用 .now() ,然后尝试模拟它。这样做的原因是因为我认为我可以让我的测试使用未模拟的方法然后模拟它,这样我的 SUT 就可以使用模拟的形式。

我最终改变了一点,取而代之的是嘲笑ZonedDateTime.ofInstant(obj,obj)。这就是我所做的

@Test
    public void renamingToArbitraryMethodName() throws Exception {
        ZonedDateTime current = ZonedDateTime.now();
        ZonedDateTime mockMidNight = ZonedDateTime.of(current.getYear(), current.getMonthValue(),
                                                      current.getDayOfMonth(), 0, 0, 0, 0, ZoneId.of("US/Eastern"));

        PowerMockito.mockStatic(ZonedDateTime.class);
        PowerMockito.when(ZonedDateTime.ofInstant(anyObject(), anyObject())).thenReturn(mockTime);
    }

在我的场景中,这对我有用,因为我能够使用 .now() 摆脱我的测试类,而我的 SUT 源使用 .ofInstant(...)

【讨论】:

    【解决方案2】:

    您正在尝试模拟 java.time 类,这意味着您正在尝试模拟系统类。这需要您put your own system under test in the @PrepareForTest annotation,因为 PowerMock 无法拦截您正在调用的类的加载,因此它必须拦截您的类的加载并在那里进行字节码重写。

    (这与您的错误消息不完全匹配,但仍然是您在这里遇到麻烦的一个非常清楚的原因,而在 Mockito 和 PowerMock 中使用非系统类都不会遇到这种情况。)

    模拟系统类的危险——除了你在模拟数据对象,尤其是具有显式单元测试功能的对象(如 cmets 中提到的时钟覆盖 Andy Turner)——是一个很好的理由 不在这里使用模拟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多