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 期间,我阅读了迁移指南,其中解释了:
- 如何使用更改后的
Promise
和 Future
Vertx 接口
- 如何在 Vertx 测试中
VertxTestContext
、Vertx
自动注入
- 如何使用
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
- 或直到异步插入完成才会阻塞,这样我的断言returns就成功了
问题:
- 如何等待异步 mongo 查询完成才能继续我的测试?
问题是我正在使用 VertX Promise
和 Future
类:
- 那些 类 只能在 VertX 上工作
Verticle
- 我的
insertTestData()
方法 未在 Verticle 上执行
一个解决方案是使用 java.util.concurrent.ReentrantLock
和 Condition
类 代替:
@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 从 JUnit4 迁移到 JUnit5 期间,我阅读了迁移指南,其中解释了:
- 如何使用更改后的
Promise
和Future
Vertx 接口 - 如何在 Vertx 测试中
VertxTestContext
、Vertx
自动注入 - 如何使用
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
- 或直到异步插入完成才会阻塞,这样我的断言returns就成功了
问题:
- 如何等待异步 mongo 查询完成才能继续我的测试?
问题是我正在使用 VertX Promise
和 Future
类:
- 那些 类 只能在 VertX 上工作
Verticle
- 我的
insertTestData()
方法 未在 Verticle 上执行
一个解决方案是使用 java.util.concurrent.ReentrantLock
和 Condition
类 代替:
@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();
}
}
}