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

如何让测试等待Verticle完全部署后再执行?

Vert.x测试等待Verticle完全部署的解决方案

问题描述

我在为Vert.x API编写测试时遇到了问题:使用OpenAPI从api-curio schema registry下载的配置设置路由,应用本身运行正常,但部分测试无法正常工作,测试似乎在路由实际设置完成前就已执行。需要让测试等待Verticle完全部署后再执行。

问题代码

测试类中的@BeforeEach方法

@BeforeEach
void deploy_verticle(Vertx vertx, VertxTestContext testContext) {
  mainVerticle = new MainVerticle();
  client = vertx.createHttpClient();
  ConfigStoreOptions propertyFile = new ConfigStoreOptions()
    .setType("file")
    .setFormat("properties")
    .setConfig(new JsonObject().put("path", "src/main/resources/local_config.properties"));
  ConfigRetrieverOptions options = new ConfigRetrieverOptions()
    .addStore(propertyFile);
  ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
  retriever.getConfig(config -> vertx.deployVerticle(mainVerticle, new DeploymentOptions().setConfig(config.result()), testContext.succeedingThenComplete()));
}

测试方法

@Test
void listEmployeTest(Vertx vertx, VertxTestContext testContext) throws Throwable {
  HttpClient client = vertx.createHttpClient();
  client.request(HttpMethod.GET, 8080, "localhost", "/v2.3/employes/").compose(request -> request.send()).onSuccess(body -> {
    assertEquals(200, body.statusCode());
    testContext.completeNow();
  }).onFailure(failure -> testContext.failNow(failure));
}

问题原因

Vert.x的vertx.deployVerticle方法默认只等待Verticle实例启动完成,不会等待Verticle内部的异步初始化逻辑(比如从schema registry下载配置、初始化路由等)执行完毕。如果你的MainVerticle的start方法里包含这些异步操作,测试会在这些操作完成前就开始执行,导致请求找不到路由或返回错误。

解决方案

1. 修改MainVerticle的start方法,用Promise控制部署完成时机

在MainVerticle的start方法中传入Promise<Void>,在所有异步初始化操作(下载schema、设置路由、启动HTTP服务器等)完成后调用promise.complete(),让Vert.x等待所有异步任务结束后再标记Verticle部署成功。

示例代码:

public class MainVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    // 加载配置
    ConfigRetriever retriever = ConfigRetriever.create(vertx);
    retriever.getConfig(configResult -> {
      if (configResult.failed()) {
        startPromise.fail(configResult.cause());
        return;
      }
      JsonObject config = configResult.result();

      // 异步下载OpenAPI schema
      vertx.createHttpClient()
        .request(HttpMethod.GET, config.getInteger("schema.port"), config.getString("schema.host"), config.getString("schema.path"))
        .compose(HttpClientRequest::send)
        .compose(HttpClientResponse::body)
        .onSuccess(schemaBody -> {
          // 基于schema初始化路由
          Router router = Router.router(vertx);
          // 这里添加路由设置逻辑
          // ...

          // 启动HTTP服务器
          vertx.createHttpServer()
            .requestHandler(router)
            .listen(config.getInteger("http.port"), listenResult -> {
              if (listenResult.succeeded()) {
                // 所有异步操作完成,标记Verticle部署成功
                startPromise.complete();
              } else {
                startPromise.fail(listenResult.cause());
              }
            });
        })
        .onFailure(startPromise::fail);
    });
  }
}

2. 保持测试类部署逻辑不变

原@BeforeEach方法无需修改,此时vertx.deployVerticle会等待MainVerticle的startPromise完成后才触发testContext.succeedingThenComplete(),确保测试在所有初始化操作完成后才执行。

额外优化建议

  • 测试中复用同一个HttpClient实例,避免每个测试方法重复创建,减少资源消耗。
  • 在@AfterEach方法中清理资源:
@AfterEach
void tearDown(Vertx vertx, VertxTestContext testContext) {
  if (client != null) {
    client.close();
  }
  vertx.undeploy(mainVerticle.deploymentID(), testContext.succeedingThenComplete());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:40:23