Как использовать Async.await () в Vert.x JUnit без нажатия "VertxException: Thread blocked"?

vorburger спросил: 12 мая 2018 в 04:37 в: vert.x

Что я делаю неправильно в этом типе теста прокси-сервера Vert.x (сгенерированного):

@RunWith(VertxUnitRunner.class)
public class MinecraftTest {    @Rule public RunTestOnContext contextRule = new RunTestOnContext();
    @Rule public Timeout timeoutRule = Timeout.seconds(7);    @Test
    public void testWhenCommand(TestContext testContext) {
        TestMinecraft testMinecraftServer = new TestMinecraft();
        new ServiceBinder(contextRule.vertx()).setAddress(Minecraft.ADDRESS).register(Minecraft.class, testMinecraftServer);        Minecraft minecraftAPI = Minecraft.createProxy(contextRule.vertx());        Async commandRegistrationAsync = testContext.async();
        minecraftAPI.newCommand("", "test", event -> {
            System.out.println("whenCommand callback");
            commandRegistrationAsync.complete();
            System.out.println("whenCommand callback complete");
        });
        commandRegistrationAsync.awaitSuccess();        testMinecraftServer.invokeCommand("test");
    }
}

Где Minecraft - @VertxGen @ProxyGen. Это не так:

Jun 05, 2018 8:07:04 PM io.vertx.core.impl.BlockedThreadChecker
WARNING: Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 2802 ms, time limit is 2000
(...)
io.vertx.core.VertxException: Thread blocked
    at sun.misc.Unsafe.park(Native Method)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
(...)
    at io.vertx.ext.unit.impl.CompletionImpl.awaitSuccess(CompletionImpl.java:80)
    at ch.vorburger.minecraft.storeys.api.test.MinecraftTest.testWhenCommand(MinecraftTest.java:56)

Полный пример доступен для тестирования здесь:

git clone https://github.com/vorburger/minecraft-storeys-maker.git
cd minecraft-storeys-maker/api
git checkout 48a44c512fe4d8001906e79de4b773fd66346584
../gradlew test

1 ответ

Xargos ответил: 12 мая 2018 в 05:29

Это исключение не означает, что тест завершился неудачно. Это так, что vertx уведомляет вас о том, что что-то не так, потому что поток заблокирован (как в обработке некоторого запроса) слишком долго. Правильный асинхронный, неблокирующий способ выполнения этого теста будет таким:

public void testWhenCommand(TestContext testContext) {
    TestMinecraft testMinecraftServer = new TestMinecraft();
    new ServiceBinder(contextRule.vertx()).setAddress(Minecraft.ADDRESS).register(Minecraft.class, testMinecraftServer);    Minecraft minecraftAPI = Minecraft.createProxy(contextRule.vertx());    Async commandRegistrationAsync = testContext.async();
    minecraftAPI.newCommand("", "test", event -> {
        System.out.println("whenCommand callback");
        testMinecraftServer.invokeCommand("test");
        commandRegistrationAsync.complete();
        System.out.println("whenCommand callback complete");
    });
}

Таким образом,

testMinecraftServer.invokeCommand("test");

вызываемый при завершении асинхронного вызова, но поток, который он сам не вешает, ожидает результата.

Для вызова блокирующего ввода-вывода вы должны использовать

executeBlocking

метод.