使用MockWebServer模拟Retrofit嵌套API调用第二请求超时如何解决?
问题解决方案
核心错误原因
- Retrofit实例未绑定到启动的MockWebServer:你创建Retrofit时
baseUrl写死为/,没有指向本地启动的MockWebServer监听地址,所以第二个请求直接走真实网络请求,自然触发超时。 - MockResponse构造错误:
setResponseCode方法仅接收HTTP状态码参数,响应体需要单独调用setBody()方法设置,同时要注意返回格式和Retrofit的转换器匹配,需要将返回值转成对应序列化框架(Jackson/Gson)可识别的字符串格式。 - 补充:你的
MyApi中cancelOrder方法缺少Retrofit参数注解(比如@Body/@Field),运行时会直接报错,需要先补上。
修正后的代码
接口定义修正
public interface MyApi{ @POST("/api/get-orders") retrofit2.Response<Set<String>> getOrders(); // 补上参数注解,这里以表单参数为例,可根据你的实际逻辑调整 @FormUrlEncoded @POST("/api/cxl-order") retrofit2.Response<String> cancelOrder(@Field("ordeId") String ordeId); }
测试代码修正
@Test public void cancel_order() throws IOException { MockWebServer server = new MockWebServer(); // 启动本地Mock服务 server.start(); String orderId ="OrderId_123"; // 核心修正:Retrofit绑定MockWebServer的监听地址 MyApi mockApi = new Retrofit.Builder() .baseUrl(server.url("/")) // 补充对应序列化转换器,这里用Jackson做示例,可根据你实际用的库调整 .addConverterFactory(JacksonConverterFactory.create()) .build() .create(MyApi.class); MyExchange exchange = new MyExchange(mockApi); // 按请求顺序入队响应,先设置状态码再设置JSON格式的响应体 // 第一个响应对应cancelOrder请求,返回字符串类型的订单ID server.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_OK) .setBody("\"" + orderId + "\"")); // 第二个响应对应嵌套调用的getOrders请求,返回空集合 server.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_OK) .setBody("[]")); // 执行测试逻辑 boolean result = exchange.cancelOrder(orderId); // 可添加断言验证结果符合预期 assertTrue(result); // 可选:验证请求顺序、路径符合预期 RecordedRequest request1 = server.takeRequest(); assertEquals("/api/cxl-order", request1.getPath()); RecordedRequest request2 = server.takeRequest(); assertEquals("/api/get-orders", request2.getPath()); // 测试结束关闭Mock服务 server.shutdown(); }
原理解释
MockWebServer是在本地随机端口启动的HTTP服务,只有发往这个服务地址的请求才会匹配你入队的MockResponse,入队的响应严格按照请求到达的顺序返回,只要Retrofit绑定正确,嵌套调用的请求也会按顺序拿到对应的响应。
内容的提问来源于stack exchange,提问作者CaptainHastings
相关产品推荐
相关产品推荐

