首页 > 解决方案 > 如何让测试等待 Vert.x Verticle 部署完成

问题描述

我正在为我的 Vert.x 应用程序实现测试,但是在让 Vert.x 以优雅的方式等待 Verticle 的部署时遇到了问题。这是我的@BeforeClass 方法:

    @BeforeClass
public static void before(TestContext context) 
{
    vertx = Vertx.vertx();
    DeploymentOptions options = new DeploymentOptions();

    byte[] encoded;
    JsonObject config;

    try {
        encoded = Files.readAllBytes(Paths.get("src/main/resources/config.json"));
        config = new JsonObject(new String(encoded, Charset.defaultCharset()));

        options.setConfig(config);
        jdbc = JDBCClient.createShared(vertx, config , "PostgreSQL");

        deployVerticle((result) -> loadTestData((result), jdbc), options);

        while (true)
            {
            if (vertx.deploymentIDs().size() > 0)
                break;
            }
    } catch 
    (IOException e) 
    {
        e.printStackTrace();
    }
}

此外,这里是 deployVerticle 和 loadTestData 方法的实现:

private static void deployVerticle(Handler<AsyncResult<Void>> next, DeploymentOptions options) {


    vertx.deployVerticle(PostgreSQLClientVerticle.class.getName(), options, deployResult -> 
    {
        if (deployResult.succeeded())
        next.handle(Future.succeededFuture());
    });
}
private static void loadTestData(AsyncResult<Void> previousOperation, JDBCClient jdbc)
{
    if (previousOperation.succeeded())
    {
        jdbc.getConnection(connection -> {
            if (connection.succeeded())
            {
                connection.result().query(deleteTestDataGeneration, queryResult -> 
                {
                    connection.result().close();
                });
            }
        });
    }
}

如您所见,现在我有一个while (true)方法before来保存进程并确保实际部署了verticle。否则,当测试开始运行时,verticle 尚未完全部署,我NullPointerException尝试获取资源。

我尝试了许多不同的方法,例如使用 CompositeFuture 或使用 Future.compose 方法来使“之前的任务”连续并让程序等待完成。我在使这些任务按顺序完成方面取得了成就,但未能在完成之前保持该过程。

我认为,其中一个问题是,deployVerticle 方法在“部署过程”的每一步完成后返回AsyncResultwith succeeded == true,而不是在 Verticle 完全启动时返回。

这意味着该过程在一切真正启动之前就获得了成功的结果……但这只是一个疯狂的猜测。

底线:我想找到一种方法来等待 Verticle 完全部署,然后再继续执行测试,而不必执行while (true)我目前在那里的循环。

标签: javatestingjunitservicevert.x

解决方案


你缺少的是Async async = context.async();. 这样,unittest 将保留在方法中,直到它未设置为完成。然后,您可以将异步代码编排为:

  • 首先部署verticle
  • 然后执行 loadtestGeneration
  • 将异步设置为完成,以便其他单元测试方法已经可以在没有 nullpointerexception 的情况下访问您的 Verticle

我也做了一些清理,检查一下:

课前

  @BeforeClass
  public static void before2(TestContext context){
    Async async = context.async();
    vertx = Vertx.vertx();
    DeploymentOptions options = new DeploymentOptions();
    byte[] encoded;
    JsonObject config;

    try {
      encoded = Files.readAllBytes(Paths.get("src/main/resources/config.json"));
      config = new JsonObject(new String(encoded, Charset.defaultCharset()));
      options.setConfig(config);
      jdbc = JDBCClient.createShared(vertx, config , "PostgreSQL");

      deployVerticle2(options)
        .compose(c -> loadTestData2(jdbc))
        .setHandler(h -> {
          if(h.succeeded()){
            async.complete();
          }else{
            context.fail(h.cause());
          }
        });

    } catch (IOException e){
      context.fail(e);
    }
  }

部署Verticle

  private static Future<Void> deployVerticle2(DeploymentOptions options) {
    Future<Void> future = Future.future();

    vertx.deployVerticle(PostgreSQLClientVerticle.class.getName(), options, deployResult -> {
      if (deployResult.failed()){
        future.fail(deployResult.cause());
      }else {
        future.complete();
      }
    });

    return future;
  }

加载测试数据

  private static Future<Void> loadTestData2(JDBCClient jdbc){
    Future<Void> future = Future.future();

    jdbc.getConnection(connection -> {
      if (connection.succeeded()) {
        connection.result().query(deleteTestDataGeneration, queryResult -> {
          if(queryResult.failed()){
            connection.result().close();
            future.fail(queryResult.cause());
          }else{
            connection.result().close();
            future.complete();
          }
        });
      } else {
        future.fail(connection.cause());
      }
    });

    return future;
  }

推荐阅读