问题描述
使用powermockito静态方法模拟时,我遇到了奇怪的行为。
注意: 2020-08-27
是执行测试时的实际系统时间。
在上面的代码示例中,您可以看到我模拟了LocalDate.Now()
方法的所有实现和LocalDateTime.Now()
方法的所有实现。我想同时实现LocalDateTime.of(LocalDate,LocalTime)
方法的真正实现。
在我调用LocalDateTime.of(LocalDate,LocalTime)
方法之前,所有模拟都正常工作。
在调用LocalDateTime.Now()
之后调用LocalDateTime.of(LocalDate,LocalTime)
时,我得到的是真实系统时间,而不是第一次的模拟值。但是,如果我再次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("");
}
}
我花了几个小时来寻找根本原因,但不幸的是还没有运气。有人可以告诉我这里有什么问题吗?
解决方法
这看起来像是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,Clock.class)).toReturn(localDate);
PowerMockito.stub(PowerMockito.method(LocalDateTime.class,"now")).toReturn(localDateTime);
PowerMockito.stub(PowerMockito.method(LocalDateTime.class,ZoneId.class)).toReturn(localDateTime);
PowerMockito.stub(PowerMockito.method(LocalDateTime.class,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
为一组选定的方法定义模拟行为,如果调用,其他方法将调用真实方法。