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

如何在Spring上下文初始化前Mock REST服务器?

如何用MockRestServiceServer测试构造函数中发起请求的Spring Bean

你的MyService在初始化阶段就通过RestTemplateBuilder创建RestTemplate并调用远程接口,这种场景下要避免真实请求,用MockRestServiceServer来模拟响应的核心思路是:让MyService使用的RestTemplate和MockServer绑定的是同一个实例,这样MockServer才能拦截到构造函数里发起的请求。下面是具体的实现步骤和代码示例:

步骤1:准备绑定了MockServer的RestTemplate

首先创建一个普通的RestTemplate,然后用MockRestServiceServer.createServer()把它和MockServer绑定,这样这个RestTemplate的所有请求都会被MockServer拦截。

步骤2:自定义RestTemplateBuilder返回绑定好的RestTemplate

因为你的MyService是通过builder.build()创建RestTemplate的,所以我们需要自定义一个RestTemplateBuilder,让它的build()方法直接返回我们刚才绑定了MockServer的RestTemplate,确保MyService拿到的是同一个实例。

步骤3:设置Mock响应规则

指定要拦截的请求URL、请求方法,然后返回预设的响应数据(可以是JSON字符串,或者用ObjectMapper把对象转成JSON)。

步骤4:初始化MyService并验证

最后创建MyService实例,此时构造函数发起的请求会被MockServer拦截并返回预设响应,之后验证Mock请求是否被触发,以及MyService的settings是否正确。

完整测试代码示例

import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
import static org.junit.jupiter.api.Assertions.*;

class MyServiceTest {

    @Test
    void testMyServiceInitialization() throws Exception {
        // 1. 创建RestTemplate并绑定MockRestServiceServer
        RestTemplate restTemplate = new RestTemplate();
        MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);

        // 2. 自定义RestTemplateBuilder,确保build()返回绑定好的RestTemplate
        RestTemplateBuilder mockBuilder = new RestTemplateBuilder() {
            @Override
            public RestTemplate build() {
                return restTemplate;
            }
            // 如果你的业务代码用到了builder的其他配置(比如超时),重写对应的方法即可
            // 示例:
            // @Override
            // public RestTemplateBuilder setConnectTimeout(Duration connectTimeout) {
            //     // 这里可以实际配置restTemplate的超时,或者直接返回this忽略配置(根据测试需求)
            //     restTemplate.getInterceptors().add(...);
            //     return this;
            // }
        };

        // 3. 准备测试数据和Mock规则
        String testUrl = "http://test-url.com/settings";
        MySettingsFromRemote mockSettings = new MySettingsFromRemote();
        mockSettings.setSomeProperty("test-value"); // 设置你需要测试的属性

        // 用ObjectMapper把对象转成JSON,避免手动写JSON出错
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResponse = objectMapper.writeValueAsString(mockSettings);

        // 设置Mock预期:匹配指定URL和GET方法,返回预设的JSON响应
        mockServer.expect(requestTo(testUrl))
                .andExpect(method(HttpMethod.GET))
                .andRespond(withSuccess()
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(jsonResponse));

        // 4. 初始化MyService,构造函数的请求会被MockServer拦截
        MyService myService = new MyService(mockBuilder, testUrl);

        // 5. 验证Mock请求被触发,并且settings属性正确
        mockServer.verify(); // 验证预期的请求确实被发起了
        assertNotNull(myService.settings);
        assertEquals("test-value", myService.settings.getSomeProperty());
    }
}

注意事项

  • 如果你的业务代码中对RestTemplateBuilder做了额外配置(比如设置超时、添加拦截器),需要在自定义的RestTemplateBuilder中重写对应的方法,确保这些配置被应用到我们绑定了MockServer的RestTemplate上,或者根据测试需求模拟这些配置。
  • 如果不需要启动Spring上下文,这种纯单元测试的方式速度更快;如果需要在集成测试中使用,可以通过自定义测试配置类,把我们的RestTemplateBuilder注册为bean,让Spring容器注入给MyService。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:03:18