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

Mockito单元测试:如何模拟对象的链式方法调用?

别担心,刚开始接触Mockito确实容易卡壳,我来帮你把这段测试代码补全,顺便把关键逻辑解释清楚~

完整的测试代码示例

首先,先把你没写完的代码补全,同时覆盖无处理错误和有处理错误两种测试场景:

import static org.mockito.Mockito.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

// 假设你的测试类结构
public class YourServiceTest {

    @Test
    public void testDeleteOperation_WithAndWithoutErrors() {
        // 1. Mock 依赖的核心对象
        CatalogFramework catalogFramework = mock(CatalogFramework.class);
        DeleteResponse deleteResponse = mock(DeleteResponse.class);

        // 2. 配置:当调用catalogFramework的delete方法时,返回我们mock的DeleteResponse
        when(catalogFramework.delete(any(DeleteRequest.class))).thenReturn(deleteResponse);

        // --------------------------
        // 场景1:删除操作无处理错误
        // --------------------------
        Set<ProcessingError> emptyErrorSet = new HashSet<>();
        when(deleteResponse.getProcessingErrors()).thenReturn(emptyErrorSet);

        // 这里调用你要测试的业务方法(比如你的Service里的删除方法)
        // yourService.performDelete(someDeleteRequest);

        // 验证结果:处理错误集合为空
        assertTrue(deleteResponse.getProcessingErrors().isEmpty());

        // --------------------------
        // 场景2:删除操作存在处理错误
        // --------------------------
        // 如果ProcessingError是复杂对象,也可以mock它,不用创建真实实例
        ProcessingError mockError = mock(ProcessingError.class);
        when(mockError.getErrorCode()).thenReturn("INVALID_ID");
        when(mockError.getMessage()).thenReturn("目标ID不存在");

        Set<ProcessingError> errorSetWithIssues = new HashSet<>();
        errorSetWithIssues.add(mockError);
        // 重置mock的返回值,切换到有错误的场景
        when(deleteResponse.getProcessingErrors()).thenReturn(errorSetWithIssues);

        // 再次调用业务方法或者直接验证
        assertFalse(deleteResponse.getProcessingErrors().isEmpty());
        assertEquals(1, deleteResponse.getProcessingErrors().size());
        assertEquals("INVALID_ID", deleteResponse.getProcessingErrors().iterator().next().getErrorCode());
    }
}

关键知识点说明

  • 必须mock依赖对象:你代码里的catalogFramework肯定是业务逻辑依赖的外部对象,所以一定要先mock它,不然调用catalogFramework.delete()会触发真实逻辑或者空指针
  • 灵活模拟返回值:针对getProcessingErrors(),你可以根据测试场景返回空集合或带元素的集合,这样就能覆盖删除成功和失败的分支逻辑
  • 静态导入简化代码:记得导入org.mockito.Mockito的静态方法(import static org.mockito.Mockito.*;),这样写when()、mock()这些方法时不用加类名前缀
  • JUnit集成建议:如果用JUnit 5,记得给测试类加@ExtendWith(MockitoExtension.class);如果是JUnit 4,用@RunWith(MockitoJUnitRunner.class),这样Mockito会自动帮你初始化mock对象,不用手动处理

更简洁的写法(用Mockito注解)

如果觉得手动mock()太麻烦,可以用Mockito的注解来简化:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class YourServiceTest {

    @Mock
    private CatalogFramework catalogFramework;
    @Mock
    private DeleteResponse deleteResponse;

    @Test
    public void testDeleteOperation() {
        // 直接配置mock行为即可,不用手动创建mock实例
        when(catalogFramework.delete(any(DeleteRequest.class))).thenReturn(deleteResponse);
        
        // 后续逻辑和之前一致...
    }
}

内容的提问来源于stack exchange,提问作者John Lippson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:58:27