Vertx中createHttpClient().getNow()未调用处理器问题求助
我来帮你排查这个问题,这种情况在Vert.x异步测试场景里挺常见的,主要有几个可能的原因,咱们一个个拆解分析:
你的serverIsStarted测试方法是同步结束的,但getNow是异步操作——测试框架很可能在HTTP请求的回调执行前,就已经判定测试完成并结束了,导致你看不到Handler runnin...的输出。
解决办法是用TestContext的async()创建一个异步等待对象,在回调里标记操作完成:
@Test public void serverIsStarted(TestContext context) { Async async = context.async(); // 创建异步等待实例,让测试框架等这个信号 vertx.createHttpClient().getNow(8080, "localhost", "/inexistent", response -> { System.out.println("Handler runnin..."); async.complete(); // 标记异步请求完成,测试框架才会结束测试 }); }
有可能你的MainVerticle并没有在8080端口启动HTTP服务器,或者绑定的地址不是localhost(比如绑定了0.0.0.0其实也能通,但如果绑定了其他特定IP就会出问题)。
可以检查MainVerticle的启动代码,确保服务器监听的是正确的端口和地址:
@Override public void start(Promise<Void> startPromise) { vertx.createHttpServer() .requestHandler(routingContext -> { // 你的请求处理逻辑 }) .listen(8080, "localhost", res -> { if (res.succeeded()) { System.out.println("Server started on http://localhost:8080"); startPromise.complete(); } else { startPromise.fail(res.cause()); } }); }
虽然你用了context.asyncAssertSuccess()等待Verticle部署成功,但如果MainVerticle的start方法里,服务器启动是异步操作(比如listen本身是异步的),Verticle部署成功不代表服务器已经完全启动并开始监听端口了。
上面的代码示例里,我们用Promise来控制Verticle的部署完成时机——只有当服务器listen成功后,才调用startPromise.complete(),这样context.asyncAssertSuccess()会真正等待服务器启动完成,再执行测试里的HTTP请求。
如果请求本身因为连接超时、拒绝等问题失败,也不会触发正常的响应回调。可以给HttpClient添加异常处理器,查看具体错误:
@Test public void serverIsStarted(TestContext context) { Async async = context.async(); HttpClient client = vertx.createHttpClient(new HttpClientOptions() .setConnectTimeout(5000) // 设置5秒连接超时 .setIdleTimeout(5000)); client.getNow(8080, "localhost", "/inexistent", response -> { System.out.println("Handler runnin..."); async.complete(); }).exceptionHandler(err -> { // 打印异常信息,快速定位问题 System.err.println("Request failed: " + err.getMessage()); async.complete(); }); }
内容的提问来源于stack exchange,提问作者antonro

