使用MockWebServer测试WebClient集成时遇域名解析问题求助
你的问题出在CardService中硬编码了完整的请求URI,导致WebClient配置的baseUrl被完全忽略。
原代码里uri("http://user-service/api/user", ...)传入了完整的HTTP地址,这会直接覆盖WebClient构建时设置的baseUrl(server.url("").toString())。所以测试时WebClient依然尝试请求user-service这个域名,而非你启动的MockWebServer地址,自然会触发域名解析失败的错误。
1. 修改业务代码:使用相对路径,依赖WebClient的baseUrl
生产环境中你原本通过Eureka和负载均衡解析user-service,业务代码根本不需要硬编码完整URL,应该用相对路径让负载均衡组件处理服务名解析。调整CardService的getUsername方法:
public UserResponse getUsername(String username) { return webClient.get() // 使用相对路径,WebClient会自动拼接baseUrl前缀 .uri(uriBuilder -> uriBuilder.path("/api/user") .queryParam("username", username) .build()) .retrieve() .bodyToMono(UserResponse.class) .block(); }
2. 补全UserResponse的Getter方法
你的UserResponse类缺少id的getter方法,Jackson反序列化后无法读取id值,测试断言会直接失败。补全代码:
public class UserResponse { private Long id; public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
3. 测试代码无需改动
你的测试代码配置本身是正确的,修改业务代码后,WebClient会自动使用MockWebServer的baseUrl发送请求,就能收到你预设的MockResponse了。
如果确实无法修改业务代码,你可以通过本地hosts文件把user-service映射到MockWebServer的IP(比如127.0.0.1 user-service),同时给MockWebServer指定固定端口:
@BeforeEach void setup() { server = new MockWebServer(); // 指定固定端口,方便hosts映射 server.start(8080); WebClient webClient = WebClient.builder().build(); service = new CardService(webClient); }
但这种方式不够优雅,优先推荐修改业务代码使用相对路径,这更符合微服务负载均衡的最佳实践。
内容的提问来源于stack exchange,提问作者mateusz-tbh

