【问题标题】:VertX JUnit 5 MongoDB test does not complete (TimeoutException) or completes too early (testContext.awaitCompletion not working)VertX JUnit 5 MongoDB 测试未完成 (TimeoutException) 或完成太早 (testContext.awaitCompletion 不起作用)
【发布时间】:2019-12-04 20:12:27
【问题描述】:

背景:

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

  • 如何使用更改后的PromiseFuture Vertx 接口
  • 如何在 Vertx 测试中 VertxTestContextVertx 自动注入
  • 如何使用testContext.awaitCondition()textContext.completing()testContext.completeNow()

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

测试代码:

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;
    }
}

问题:

  • testContext.awaitCompletion() ether 抛出 TimeoutException
  • 在异步插入完成之前不会阻塞以便我的断言成功返回

问题:

  • 如何等待异步 mongo 查询完成,然后再继续测试?

【问题讨论】:

    标签: mongodb promise async-await vert.x junit5


    【解决方案1】:

    问题是我正在使用 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();
            }
        }
    }
    

    【讨论】:

    • 说实话:我花了很长时间才找到我在这里记录的错误/解决方案,因为我可能隐含地预计 VertX PromiseFuture 类会抛出某种错误或在Verticle 之外使用时发出警告。
    猜你喜欢
    • 2013-09-30
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    相关资源
    最近更新 更多