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

SpringBoot应用中如何Mock外部URL响应以测试API全流程?

测试SpringBoot完整流程并Mock外部REST请求

针对你这种Controller→Service→ClientClass的调用链,且外部URL不可用的场景,有两种常用的Mock方案,都能覆盖从Controller开始的完整流程:

方案一:用Mockito直接Mock RestTemplate

这种方式适合快速Mock单个外部请求,无需启动额外服务。

步骤:

  1. 确保测试依赖齐全
    你的pom.xml(Maven)或build.gradle(Gradle)里要包含Spring Boot测试 starter,它自带Mockito:

    <!-- Maven -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
  2. 编写测试类
    使用@SpringBootTest加载完整应用上下文,用@MockBean替换真实的RestTemplate,然后指定Mock的响应逻辑:

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.client.RestTemplate;
    import static org.mockito.ArgumentMatchers.any;
    import static org.mockito.ArgumentMatchers.eq;
    import static org.mockito.Mockito.when;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.context.ApplicationContext;
    
    @SpringBootTest
    public class FullFlowTest {
        @Autowired
        private ApplicationContext context;
        private MockMvc mockMvc;
    
        @MockBean
        private RestTemplate restTemplate;
    
        @Test
        public void testFullFlow() throws Exception {
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
            
            // 定义Mock的外部响应内容
            String mockExternalResponse = "{\"code\":200,\"msg\":\"success\"}";
            when(restTemplate.postForEntity(
                eq("http://external-url.com/api"), // 匹配目标URL
                any(Object.class), // 匹配任意请求体
                eq(String.class) // 匹配响应类型
            )).thenReturn(new ResponseEntity<>(mockExternalResponse, HttpStatus.OK));
    
            // 发起对Controller的请求,验证完整流程
            mockMvc.perform(post("/your-controller-endpoint")
                    .contentType("application/json")
                    .content("{\"requestData\":\"test\"}"))
                    .andExpect(status().isOk());
        }
    }
    

方案二:用WireMock模拟完整外部服务

如果需要模拟更复杂的外部服务行为(比如不同请求返回不同响应、模拟异常),WireMock是更好的选择。

步骤:

  1. 添加WireMock依赖

    <!-- Maven -->
    <dependency>
        <groupId>com.github.tomakehurst</groupId>
        <artifactId>wiremock-jre8</artifactId>
        <scope>test</scope>
        <version>2.35.0</version>
    </dependency>
    
  2. 编写测试类
    启动WireMock服务器,配置Stub规则,然后让ClientClass指向WireMock的地址:

    import com.github.tomakehurst.wiremock.WireMockServer;
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.context.ApplicationContext;
    import static com.github.tomakehurst.wiremock.client.WireMock.*;
    
    @SpringBootTest(properties = {"external.api.url=http://localhost:8089/api"})
    public class WireMockFullFlowTest {
        @Autowired
        private ApplicationContext context;
        private MockMvc mockMvc;
        private WireMockServer wireMockServer;
    
        @BeforeEach
        void setup() {
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
            // 启动WireMock服务器,监听8089端口
            wireMockServer = new WireMockServer(8089);
            wireMockServer.start();
            configureFor("localhost", 8089);
            
            // 配置Stub:匹配POST请求,返回指定响应
            stubFor(post(urlEqualTo("/api"))
                    .willReturn(aResponse()
                            .withStatus(200)
                            .withHeader("Content-Type", "application/json")
                            .withBody("{\"code\":200,\"msg\":\"success\"}")));
        }
    
        @Test
        public void testFullFlowWithWireMock() throws Exception {
            // 发起对Controller的请求,验证完整流程
            mockMvc.perform(post("/your-controller-endpoint")
                    .contentType("application/json")
                    .content("{\"requestData\":\"test\"}"))
                    .andExpect(status().isOk());
        }
    
        @AfterEach
        void teardown() {
            wireMockServer.stop();
        }
    }
    

注意事项

  • 如果你的ClientClass是通过构造函数注入RestTemplate,Mock时要确保注入的是Mock实例
  • 用WireMock时,要把ClientClass里的外部URL配置为WireMock的地址(可以通过测试环境变量覆盖)
  • 测试时要验证不仅是状态码,还要验证业务逻辑的输出是否符合预期

内容的提问来源于stack exchange,提问作者Aslam P Sherif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:48:16