如何在Java单元测试中使用Argument Captor并Mock RestTemplate?
单元测试中Mock RestTemplate与使用Argument Captor的实现方案
针对这段发送multipart请求的代码,我们可以用Mockito框架来Mock依赖并捕获请求参数,具体实现如下:
1. 测试类基础配置
先在测试类中完成Mock对象和目标类的初始化:
- 用
@ExtendWith(MockitoExtension.class)启用Mockito支持 - 用
@Mock注解Mock所有外部依赖:RestTemplate、PojoToMultiValueMapMapper、ClientProperties - 用
@InjectMocks注入待测试的业务类(假设该类名为PojoArchiveClient)
2. Mock RestTemplate的行为
我们不需要实际发送HTTP请求,只需MockpostForEntity方法的返回值即可:
- 指定当调用
restTemplate.postForEntity时,返回一个预设的ResponseEntity<Void>(比如ResponseEntity.ok().build()),避免触发真实网络请求。
3. 使用Argument Captor捕获并验证请求参数
为了确保构建的HttpEntity符合预期(请求头、请求体是否正确),我们用Argument Captor来捕获传入RestTemplate的参数:
- 定义
ArgumentCaptor<HttpEntity<?>>类型的捕获器,可通过@Captor注解或ArgumentCaptor.forClass(HttpEntity.class)创建 - 在验证RestTemplate调用时,用捕获器抓取传入的
HttpEntity参数 - 从捕获器中取出
HttpEntity,分别验证请求头和请求体的正确性
完整测试代码示例
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.util.Collections; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class PojoArchiveClientTest { // 对应业务类中的静态常量 private static final String X_REQUESTING_SYSTEM_KEY = "X-Requesting-System"; private static final String X_REQUESTING_SYSTEM_VALUE = "test-system"; private static final MediaType MULTIPART_FORM_DATA_BOUNDARY = MediaType.valueOf("multipart/form-data;boundary=BOUNDARY"); @Mock @Qualifier("REST_TEMPLATE") private RestTemplate restTemplate; @Mock private PojoToMultiValueMapMapper mapper; @Mock private ClientProperties properties; @InjectMocks private PojoArchiveClient client; // 待测试的业务类 @Captor private ArgumentCaptor<HttpEntity<?>> httpEntityCaptor; @Test void archivePojo_shouldSendCorrectMultipartRequest() { // 1. 准备测试数据 Pojo testPojo = new Pojo(); String testUrl = "http://example.com/archive"; when(properties.getUrl()).thenReturn(testUrl); // Mock mapper的映射结果 MultiValueMap<String, Object> mockMultiValueMap = Collections.singletonMap("pojo-data", new Object()); when(mapper.map(testPojo)).thenReturn(mockMultiValueMap); // 2. Mock RestTemplate的postForEntity方法 when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), eq(Void.class))) .thenReturn(ResponseEntity.ok().build()); // 3. 调用待测试方法 client.archivePojo(testPojo); // 4. 验证RestTemplate调用并捕获HttpEntity参数 verify(restTemplate).postForEntity(eq(testUrl), httpEntityCaptor.capture(), eq(Void.class)); HttpEntity<?> capturedEntity = httpEntityCaptor.getValue(); // 5. 验证请求头 HttpHeaders capturedHeaders = capturedEntity.getHeaders(); assertEquals(MULTIPART_FORM_DATA_BOUNDARY, capturedHeaders.getContentType()); assertEquals(X_REQUESTING_SYSTEM_VALUE, capturedHeaders.getFirst(X_REQUESTING_SYSTEM_KEY)); // 6. 验证请求体 assertEquals(mockMultiValueMap, capturedEntity.getBody()); } }
关键细节说明
- Mock RestTemplate:通过
@Mock创建虚拟的RestTemplate实例,用when(...).thenReturn(...)指定方法返回结果,彻底隔离真实网络调用。 - Argument Captor:核心作用是抓取传入RestTemplate的
HttpEntity,从而验证请求头是否包含指定系统标识、Content-Type是否为预设的multipart类型,以及请求体是否正确映射自Pojo对象。 - 依赖注入:
@InjectMocks会自动将Mock的依赖注入到待测试类中,无需手动实例化和组装依赖。
内容的提问来源于stack exchange,提问作者Guru Cse
相关产品推荐
相关产品推荐

