You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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);
    }
}

注意:你原有的测试代码存在两处问题:

  1. myMethodToTest是业务方法,不属于MyClass,不能用mockMyClass.myMethodTotest()调用
  2. 业务代码已经捕获了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 23:42:04