为何手动等待异步事件时测试无法完成?endlessTest测试为何无法结束?
嘿,这俩测试问题我之前踩过同款坑,给你好好捋捋:
问题1:手动等异步事件时测试为啥完不成?
首先得明确:Vert.x的测试框架(不管是用JUnit 4的TestContext还是JUnit 5的VertxExtension),绝对不能用Thread.sleep()或者手动轮询变量的方式等异步操作!
你想啊,测试线程要是被while (!done[0]) { Thread.sleep(100); }这种代码堵死了,Vert.x的事件循环根本没法正常处理你的HTTP请求或者其他异步任务。而且测试框架完全不知道你在等什么,它要么会提前判定测试结束,要么就一直卡着直到超时失败。
正确姿势是用Vert.x给的Async对象,它就是用来告诉测试框架“我还有异步操作没做完,别着急结束”的:
@Test public void properAsyncTest(TestContext context) { Async async = context.async(); // 创建一个异步标记 vertx.createHttpClient().getNow(8080, "localhost", "/your-endpoint", response -> { // 先做你需要的断言,比如检查响应码 context.assertEquals(200, response.statusCode()); async.complete(); // 告诉测试框架:嘿,我搞定了,你可以结束测试了 }); }
这样测试框架会乖乖等着async.complete()被调用,既不会提前结束,也不会阻塞事件循环。
问题2:为啥endlessTest永远停不下来?
从你给的代码片段来看,核心问题还是没给测试框架正确的完成信号,再加上可能的请求异常没处理,导致测试一直挂着。
比如你用boolean[] done来标记完成,但就算你把done[0]设为true了,测试框架根本不知道啊!它还在傻等呢。另外,如果你的HTTP请求因为端口错了、Verticle没部署好,或者请求路径不对,导致请求一直挂着没响应,那done[0]永远不会变true,测试就无限卡下去了。
还有一种可能:如果你的MainVerticle里有长期运行的任务(比如定时任务、没关闭的WebSocket),不过看你的tearDown用了vertx.close(context.asyncAssertSuccess()),这个应该会把所有资源都关掉,所以大概率还是测试里的异步操作没给完成信号。
给你个修复后的endlessTest示例:
@Test public void fixedEndlessTest(TestContext context) { Async async = context.async(); vertx.createHttpClient() .getNow(8080, "localhost", "/your-path", response -> { // 做你的断言逻辑 context.assertNotNull(response); async.complete(); // 标记完成 }) .exceptionHandler(err -> { // 一定要处理异常!不然请求失败的话测试会一直挂着 context.fail("请求出错了:" + err.getMessage()); async.complete(); }); // 还可以给异步操作加个超时,避免无限等 async.await(5000); // 5秒超时 }
这样不管请求成功还是失败,都会通知测试框架结束,再也不会无限挂着了。
内容的提问来源于stack exchange,提问作者antonro

