【问题标题】:How do I unit test event handlers (from the event bus) in Vert.x?如何在 Vert.x 中对事件处理程序(来自事件总线)进行单元测试?
【发布时间】:2016-09-21 04:07:27
【问题描述】:

我是 Vert.x 3 的新手,我正在尝试为一个简单的事件处理程序编写单元测试。现在,我要做的就是检查被测试的 Verticle 是否委托给正确的组件,该组件是使用 Mockito 作为模拟创建的。

我的测试代码如下所示:

@Rule
public final RunTestOnContext vertxRule = new RunTestOnContext();

@Before
public void setUp(TestContext context) {
    vertx = vertxRule.vertx();
    //verticle is set up with mock delegate before deployment
    vertx.deployVerticle(verticle);
}

@After
public void tearDown(TestContext context) {
    vertx.close(context.asyncAssertSuccess());
}

@Test
public void testDelegate(TestContext context) {
    EventBus eventBus = vertx.eventBus();
    Event event = new Event("id", "description")
    eventBus.publish("event.channel", Json.encode(event));

    //Mockito.verify
    verify(delegate).invokeMethod(anyString(), anyString());
}

Veticle 包含类似于以下的代码:

private Delegate delegate;

@Override
public void start(Future<Void> future) throws Exception {
    vertx.eventBus().consumer("event.channel", message -> {
        logger.info("received!");
        Event event = Json.decodeValue(message.body().toString(), Event.class);
        delegate.invokeMethod(event.getId(), event.getDescription());
    });
}

但是,每次我运行测试时,我总是收到一条错误消息,指出没有调用模拟。我确信模拟对象被正确注入,因为如果我在事件总线构造之外调用它,测试就会通过。此外,代码记录了received! 信息,所以我确信测试执行达到了这一点。我只是不确定为什么在测试结束时,报告说没有与模拟对象的交互。

【问题讨论】:

    标签: java vert.x


    【解决方案1】:

    在调用 Mock 之前执行验证。您应该在验证之前等待测试中的异步。像这样:

    @Test
    public void testDelegate(TestContext context) {
        EventBus eventBus = vertx.eventBus();
        Event event = new Event("id", "description")
        Async async = context.async();
        eventBus.publish("event.channel", Json.encode(event) ,done ->async.complete());
    
    
        async.await()
    
        //Mockito.verify
        verify(delegate).invokeMethod(anyString(), anyString());
    }
    

    然后你的 Verticle 必须在调用 mock 后通过 message.reply(...) 回复收到的消息。

    在您对没有回复的评论后进行编辑

    我尝试了以下使用全局变量(丑陋)进行同步的代码(注意这是一个 io.vertx.core.Future):

    @RunWith(VertxUnitRunner.class)
    public class StackTest {
    
        private Vertx vertx;
        public static Future<String> synchronisation = Future.future();
    
        @Before
        public void setUp(TestContext context) {
            vertx = Vertx.vertx();
            vertx.deployVerticle(new StackVerticle());
        }
    
        @Test
        public void testPublish(TestContext context){
            vertx.eventBus().publish("topic","message");
            Async async = context.async();
            synchronisation.setHandler(event -> async.complete());
            async.await();
        }
    }  
    

    还有测试verticle(synchronization.complete必须由你的mock触发):

    public class StackVerticle extends AbstractVerticle {
        @Override
        public void start() throws Exception {
            vertx.eventBus().consumer("topic",received ->{
                System.out.println("received");
                StackTest.synchronisation.complete("done");
            });
        }
    }
    

    【讨论】:

    • 我不需要我的 Verticle 来回复。
    • 这是个问题。由于 eventbus.publish() 异步通知消费者,因此在测试中的下一个 java 语句(即 Mockito.verify)上继续执行。您必须找到一种方法来在您的委托被调用后执行此验证。
    猜你喜欢
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多