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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 13:05:26