如何使用Mockito和JUnit对ZonedDateTime.ofInstant方法进行Mock
实现方案
ZonedDateTime.ofInstant()是JDK提供的静态方法,常规Mockito API无法直接Mock,可选择以下两种方案实现:
方案1:使用Mockito 3.4.0+ 静态Mock能力(无需调整业务代码)
首先确保项目引入的mockito-core版本≥3.4.0,测试代码写法如下:
@Mock MyClass mockMyClass; // 替换为你实际的被测类实例,myMethodToTest属于被测类而非MyClass的方法 @InjectMocks private BizService bizService; @Test public void testmyMethodToTest_Exception() { // 前置Mock:数据库查询返回Mock的MyClass实例 when(bizService.fetchSomethingFromDB()).thenReturn(mockMyClass); // 前置Mock:getEndDt返回合法值,避免其他环节提前抛异常 when(mockMyClass.getEndDt()).thenReturn(new Date()); String error = "Error while parsing the effective end date"; // 静态Mock作用域,try代码块结束后自动释放Mock try (MockedStatic<ZonedDateTime> zonedDateTimeMock = Mockito.mockStatic(ZonedDateTime.class)) { // 配置ofInstant方法任意参数调用时抛出指定异常 zonedDateTimeMock.when(() -> ZonedDateTime.ofInstant(any(Instant.class), any(ZoneId.class))) .thenThrow(new DateTimeException(error)); // 调用被测方法 ZonedDateTime result = bizService.myMethodToTest(); // 业务代码已捕获异常返回null,直接断言返回值即可 assertNull(result); } }
注意:你原有的测试代码存在两处问题:
myMethodToTest是业务方法,不属于MyClass,不能用mockMyClass.myMethodTotest()调用- 业务代码已经捕获了
DateTimeException并返回null,测试方法不需要加expected = DateTimeException配置,异常不会向上抛出到测试层
方案2:调整业务代码避免静态Mock(更符合单测最佳实践)
静态Mock会增加单测性能开销,且作用域控制不当容易影响其他测试用例,推荐将时间转换逻辑抽离为可Mock的实例方法:
调整后业务代码:
public ZonedDateTime myMethodToTest(){ MyClass myClass; myClass = fetchSomethingFromDB(); try{ final ZoneId systemDefault = ZoneId.systemDefault(); // 调用抽离的实例方法做转换 return convertToZonedDateTime(myClass.getEndDt().toInstant(), systemDefault); } catch(DateTimeException dte) { return null; } } // 抽离为protected方法,单测时可Mock protected ZonedDateTime convertToZonedDateTime(Instant instant, ZoneId zoneId) { return ZonedDateTime.ofInstant(instant, zoneId); }
对应测试代码:
// 被测类用Spy注解,支持Mock非public的实例方法 @Spy @InjectMocks private BizService bizService; @Mock MyClass mockMyClass; @Test public void testmyMethodToTest_Exception() { when(bizService.fetchSomethingFromDB()).thenReturn(mockMyClass); when(mockMyClass.getEndDt()).thenReturn(new Date()); String error = "Error while parsing the effective end date"; // Mock抽离的转换方法抛出异常 doThrow(new DateTimeException(error)).when(bizService) .convertToZonedDateTime(any(Instant.class), any(ZoneId.class)); ZonedDateTime result = bizService.myMethodToTest(); assertNull(result); }
如果你的项目使用的Mockito版本低于3.4,也可以使用PowerMock配合@PrepareForTest(ZonedDateTime.class)注解实现静态方法Mock,整体逻辑和方案1一致。
内容的提问来源于stack exchange,提问作者Som
相关产品推荐
相关产品推荐

