【问题标题】:PowerMockito mock gets cleared after calling real method调用真实方法后,PowerMockito 模拟被清除
【发布时间】:2020-08-27 13:48:14
【问题描述】:

我在使用 PowerMockito 静态方法模拟时遇到了一种奇怪的行为。

注意:2020-08-27是执行测试时的真实系统时间。

如您所见,在上面的代码示例中,我模拟了LocalDate.now() 方法的所有实现以及LocalDateTime.now() 方法的所有实现。同时我想要LocalDateTime.of(LocalDate, LocalTime)方法的真正实现。

在我调用 LocalDateTime.of(LocalDate, LocalTime) 方法之前,所有模拟都正常工作。

当我在调用LocalDateTime.of(LocalDate, LocalTime) 之后调用LocalDateTime.now() 时,我第一次得到真正的系统时间而不是模拟值。但是,如果我再次LocalDateTime.now(),那么我将再次获得嘲笑时间。

上面附有模拟结果的调试屏幕截图。这是我正在使用的代码。

@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.dom.*"})
// This is needed due to a compatibility issue of Power Mock with JDK 9 (https://github.com/powermock/powermock/issues/864#issuecomment-447001997)
public class MainTest {

    @Test
    public void test() {
        LocalDate now = LocalDate.now();

        String dateString = "2020-08-24T09:00:00Z";
        Instant instant = Instant.parse(dateString);
        LocalDate localDate = LocalDate.ofInstant(instant, ZoneId.of("UTC"));
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC"));

        PowerMockito.mockStatic(LocalDate.class);
        PowerMockito.when(LocalDate.now()).thenReturn(localDate);
        PowerMockito.when(LocalDate.now(Mockito.any(ZoneId.class))).thenReturn(localDate);
        PowerMockito.when(LocalDate.now(Mockito.any(Clock.class))).thenReturn(localDate);

        PowerMockito.mockStatic(LocalDateTime.class);
        PowerMockito.when(LocalDateTime.of(Mockito.any(LocalDate.class), Mockito.any(LocalTime.class))).thenCallRealMethod();
        PowerMockito.when(LocalDateTime.now()).thenReturn(localDateTime);
        PowerMockito.when(LocalDateTime.now(Mockito.any(ZoneId.class))).thenReturn(localDateTime);
        PowerMockito.when(LocalDateTime.now(Mockito.any(Clock.class))).thenReturn(localDateTime);

        LocalDate now1 = LocalDate.now();
        LocalDateTime of = LocalDateTime.of(localDate, LocalTime.of(10, 30));
        LocalDate now2 = LocalDate.now();
        LocalDate now3 = LocalDate.now();
        System.out.println("");
    }
}

我已经花了几个小时寻找根本原因,但不幸的是还没有运气。谁能告诉我这里出了什么问题?

【问题讨论】:

    标签: java unit-testing mockito powermock localdate


    【解决方案1】:

    这看起来像是 PowerMockito.mockStatic 本身的错误。我也在https://github.com/powermock/powermock/issues/1066 上发布了同样的内容。但我还没有得到任何回应。无论如何,我能够使用PowerMockito.stub 方法为我的用例找到解决方案。以下代码按预期工作,没有任何问题。

    @RunWith(PowerMockRunner.class)
    @PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.dom.*"})
    // This is needed due to a compatibility issue of Power Mock with JDK 9 (https://github.com/powermock/powermock/issues/864#issuecomment-447001997)
    public class MainTest {
    
        @Test
        public void test() {
            LocalDate now = LocalDate.now();
    
            String dateString = "2020-08-24T09:00:00Z";
            Instant instant = Instant.parse(dateString);
            LocalDate localDate = LocalDate.ofInstant(instant, ZoneId.of("UTC"));
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC"));
    
            PowerMockito.stub(PowerMockito.method(LocalDate.class, "now")).toReturn(localDate);
            PowerMockito.stub(PowerMockito.method(LocalDate.class, "now", ZoneId.class)).toReturn(localDate);
            PowerMockito.stub(PowerMockito.method(LocalDate.class, "now", Clock.class)).toReturn(localDate);
    
            PowerMockito.stub(PowerMockito.method(LocalDateTime.class, "now")).toReturn(localDateTime);
            PowerMockito.stub(PowerMockito.method(LocalDateTime.class, "now", ZoneId.class)).toReturn(localDateTime);
            PowerMockito.stub(PowerMockito.method(LocalDateTime.class, "now", Clock.class)).toReturn(localDateTime);
    
            LocalDate now1 = LocalDate.now();
            LocalDateTime of = LocalDateTime.of(localDate, LocalTime.of(10, 30));
            LocalDate now2 = LocalDate.now();
            LocalDate now3 = LocalDate.now();
            System.out.println("");
        }
    }
    

    两种方法的区别在于PowerMockito.mockStatic 我模拟整个类,然后用PowerMockito.when 定义每个方法的行为。未使用PowerMockito.when 定义的方法如果被调用,将返回 null 或不执行任何操作。但是对于PowerMockito.stub,我不会嘲笑整个班级。我仅使用PowerMockito.stub 为一组选定的方法定义模拟行为,如果调用其他方法,则将调用真实方法。

    【讨论】:

      猜你喜欢
      • 2017-06-20
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      • 2019-08-29
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多