如何在Vert.x JUnit中使用Async.await()而不命中“VertxException:Thread blocked”?

时间:2018-06-05 18:17:14

标签: 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 个答案:

答案 0 :(得分:0)

此异常并不意味着测试失败。这是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");
异步调用完成后调用

,但它自己的线程不会挂起,等待结果。

要调用阻止IO,您应该使用

executeBlocking

方法