2015-09-05 500 views
4

在嘗試使用事件總線測試一個Vert.x Verticle時,我遇到了「阻塞錯誤」。這裏下來verticle和測試類:Vertx單元測試阻塞主線程

EventBusReceiverVerticle

public class EventBusReceiverVerticle extends AbstractVerticle { 

    public EventBusReceiverVerticle(String name) { 
     this.name = name; 
    } 

    public void start() { 

       vertx.eventBus().consumer("geo-service", (Message<JsonObject> handler) -> { 
      { 
       try { 
        System.out.println("sleep 10 seconds"); 
        Thread.sleep(10000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       }   
      } 
     }); 
    } 
} 

測試類:

@RunWith(VertxUnitRunner.class) 
public class MyFirstVerticleTest { 
    Vertx vertx; 
    EventBus eb; 
    private static final Logger logger = LoggerFactory.getLogger(MyFirstVerticleTest.class); 


    @Before 
    public void setUp(TestContext context) { 
     logger.info("@Before"); 
     vertx = Vertx.vertx(); 
     eb = vertx.eventBus(); 

     Async async = context.async(); 
     vertx.deployVerticle(new EventBusReceiverVerticle("R1"), res -> { 
      if (res.succeeded()) { 
       async.complete(); 
      } else { 
       context.fail(); 
      } 
     }); 
    } 

    @After 
    public void tearDown(TestContext context) { 
     logger.info("@After"); 
     Async async = context.async(); 
     vertx.close(event -> async.complete()); 
    } 


    @Test 
    public void testEventBusVerticle(TestContext context) { 
     Async async = context.async(); 
     JsonObject msg = new JsonObject("{\"action\":\"pos\"}"); 
     eb.send("geo-service", msg, reply -> { 
      if (reply.succeeded()) { 
       async.complete(); 
      } else { 
       context.fail(); 
      } 
     }); 
     async.complete(); 
    } 
} 

控制檯輸出:

Sep 05, 2015 2:20:23 PM com.company.MyFirstVerticleTest 
INFO: @Before 
sleep 10 seconds 
Sep 05, 2015 2:20:24 PM com.company.MyFirstVerticleTest 
INFO: @After 
Sep 05, 2015 2:20:27 PM io.vertx.core.impl.BlockedThreadChecker 
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 2790 ms, time limit is 2000 
Sep 05, 2015 2:20:28 PM io.vertx.core.impl.BlockedThreadChecker 
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 3794 ms, time limit is 2000 
Sep 05, 2015 2:20:29 PM io.vertx.core.impl.BlockedThreadChecker 
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 4796 ms, time limit is 2000 
Sep 05, 2015 2:20:30 PM io.vertx.core.impl.BlockedThreadChecker 
WARNING: Thread Thread[vert.x-eventloop-thread-2,5,main] has been blocked for 5799 ms, time limit is 2000 
io.vertx.core.VertxException: Thread blocked 
    at java.lang.Thread.sleep(Native Method) 
    at com.company.verticals.EventBusReceiverVerticle.lambda$start$1(EventBusReceiverVerticle.java:35) 
    at com.company.verticals.EventBusReceiverVerticle$$Lambda$10/2029238960.handle(Unknown Source) 
    at io.vertx.core.eventbus.impl.EventBusImpl$HandlerRegistration.handle(EventBusImpl.java:1108) 
    at io.vertx.core.eventbus.impl.EventBusImpl.lambda$doReceive$189(EventBusImpl.java:755) 
    at io.vertx.core.eventbus.impl.EventBusImpl$$Lambda$17/1888442711.handle(Unknown Source) 
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:314) 
    at io.vertx.core.impl.ContextImpl$$Lambda$9/911312317.run(Unknown Source) 
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:357) 
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357) 
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111) 
    at java.lang.Thread.run(Thread.java:745) 

回答

5

我不得不設置verticle爲工人設置:

new DeploymentOptions().setWorker(true) 
+0

只是好奇你用什麼記錄。我用的是vert.x提供的JUL,我的Test類沒有任何東西寫出來。當我切換到log4j時,它似乎無法找到我的log4j.xml文件。 –

+0

你只需要把你的類路徑log4j – rayman

2

另一種方法是增加超時

VertxOptions options = new VertxOptions(); 
options.setMaxEventLoopExecuteTime(Long.MAX_VALUE); 
vertx = Vertx.vertx(options);` 
+0

你不應該阻止主線程。將超時設置爲Long.MAX_VALUE可能會產生各種不良問題。如果你有可怕的阻止電話,你甚至不會知道。避免這種解決方案。 – arg20

0

關鍵句在Vertx documentation

不要擋我!

由於您在Verticle中執行了阻止代碼,因此您會收到阻止消息。調用Thread.sleep(10000)會阻止您當前的Verticle 10秒鐘。

將您的Verticle聲明爲工作人員是一種解決方法。看看Vertx文檔Executing blocking code。根據文檔,您可以告訴Vertx執行Thread.sleep(10000)作爲阻止代碼。

vertx.executeBlocking({ future -> 
    // Call some blocking API that takes a significant amount of time to return 
    Thread.sleep(10000) 
    future.complete(result) 
}, { res -> 
    println("The result is: ${res.result()}") 
}) 

也許你可以解釋你的測試目的以及爲什麼使用Thread.sleep(10000)