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
相关产品推荐
相关产品推荐

