VertX JUnit 5 MongoDB 测试未完成(TimeoutException)或完成得太早(testContext.awaitCompletion 不工作)

VertX JUnit 5 MongoDB test does not complete (TimeoutException) or completes too early (testContext.awaitCompletion not working)

背景:

在使用 VertX 从 JUnit4 迁移到 JUnit5 期间,我阅读了迁移指南,其中解释了:

考虑到这些信息,我编写了以下测试:

测试代码:

import io.vertx.core.Promise;
import io.vertx.core.Future;

@ExtendWith(VertxExtension.class)
class RestApiTest {

    @BeforeAll
    static void setUpMongoDatabase() throws IOException {
        (...)
    }

    @BeforeEach
    void setUp(Vertx vertx, VertxTestContext ctx) {
        vertx.deployVerticle(ApiVerticle.class.getName(), options, ctx.completing());
        return WebClient.create(vertx);
    }

    @AfterEach
    void tearDown(Vertx vertx, VertxTestContext testContext) {
        assertThat(vertx.deploymentIDs().size(), is(equalTo(2)));
    }

    @AfterAll
    static void stopMongoDatabase() {
        (...)
    }

    @Test
    void test(Vertx vertx, VertxTestContext testContext) {
        Future<Void> insertFuture = insertTestData();
        future.setHandler(testContext.completing());
        // This ether throws a TimeoutException or does not block until the insert completed
        testContext.awaitCompletion(5, TimeUnit.SECONDS);
        // assert
        mongoClient.findOne(COLLECTION, QUERY, result -> {
             if (result.succeeded()) testContext.completeNow();
             else testContext.failNow();
        });
    }

    Future<Void> insertTestData() {
        Promise<Void> promise = Promise.promise();
        Future<Void> future = promise.future();
        mongoClient.insert(COLLECTION, QUERY, result -> {
            if (result.succeeded()) {
                promise.complete();
            } else {
                promise.fail();
            }
        });
        return future;
    }
}

问题:

问题:

问题是我正在使用 VertX PromiseFuture 类:

  • 那些 类 只能在 VertX 上工作 Verticle
  • 我的 insertTestData() 方法 未在 Verticle 上执行

一个解决方案是使用 java.util.concurrent.ReentrantLockCondition 类 代替:

    @Test
    void test() {
        insertTestData(); // This is now synchronous as required
        // assert
        mongoClient.findOne(COLLECTION, QUERY, result -> {
             if (result.succeeded()) testContext.completeNow();
             else testContext.failNow();
        });
    }

    void insertTestData() {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        mongoClient.insert(COLLECTION, QUERY, result -> {
            if (result.succeeded()) {
                lock.lock();
                try {
                    condition.signal();
                } finally {
                    lock.unlock();
                }
            } else {
                fail();
            }
        });
        lock.lock();
        try {
            condition.await(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        } finally {
            lock.unlock();
        }
    }
}