You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vertx中用Mockito模拟Handler<AsyncResult<Void>>及参数捕获

在Vert.x中使用Mockito模拟Handler<AsyncResult>及相关场景指南

我来一步步帮你搞定Vert.x结合Mockito测试时遇到的这些问题,先从你现有代码里的小问题入手,再依次覆盖模拟Handler、AsyncHandler和参数捕获的场景。

先修复你的基础测试代码

首先你的现有代码里有两个小问题:

  1. 你要mock的是A接口,但代码里写了Mockito.mock(C.class),这会导致后续调用方法时出错;
  2. when(...)的语法不对,而且Vert.x的异步方法需要触发Handler回调才能完成测试,不能直接返回false。

下面是修正后的基础测试类结构:

@RunWith(VertxUnitRunner.class)
class C {
    protected A sampleObject;

    @Before
    public void setup(TestContext context) {
        // 正确mock接口A
        sampleObject = Mockito.mock(A.class);
    }
}

这里把@BeforeClass改成@Before是因为VertxUnitRunner通常需要实例级别的初始化,避免测试之间的状态干扰。

模拟Handler<AsyncResult>

Vert.x的异步方法依赖Handler回调来传递结果,所以mock的时候不能只做方法匹配,还要手动触发Handler的回调逻辑。我们可以用Mockito的doAnswer来捕获方法调用,然后取出Handler参数并触发它的handle方法。

模拟成功场景

@Test
public void testVerifyCredentialsSuccess(TestContext context) {
    // 配置mock:当调用verifyCredentials时,触发Handler的成功回调
    Mockito.doAnswer(invocation -> {
        // 获取传入的第二个参数(Handler)
        Handler<AsyncResult<Void>> handler = invocation.getArgument(1);
        // 触发成功回调
        handler.handle(Future.succeededFuture());
        return null;
    }).when(sampleObject).verifyCredentials(
        Mockito.any(JsonObject.class), 
        Mockito.any(Handler.class)
    );

    // 调用待测试方法并验证结果
    sampleObject.verifyCredentials(new JsonObject().put("user", "test"), ar -> {
        // 验证异步结果是否成功
        context.assertNull(ar.failed());
        // 标记测试完成
        context.completeNow();
    });
}

模拟失败场景

@Test
public void testVerifyCredentialsFailure(TestContext context) {
    // 配置mock:触发Handler的失败回调
    Mockito.doAnswer(invocation -> {
        Handler<AsyncResult<Void>> handler = invocation.getArgument(1);
        // 传入自定义异常触发失败
        handler.handle(Future.failedFuture(new RuntimeException("Invalid credentials")));
        return null;
    }).when(sampleObject).verifyCredentials(
        Mockito.any(JsonObject.class), 
        Mockito.any(Handler.class)
    );

    sampleObject.verifyCredentials(new JsonObject(), ar -> {
        // 验证异步结果是否失败
        context.assertNotNull(ar.failed());
        context.assertEquals("Invalid credentials", ar.cause().getMessage());
        context.completeNow();
    });
}

模拟AsyncHandler

其实Vert.x里的AsyncHandler<T>就是Handler<AsyncResult<T>>的类型别名,两者是完全等价的。所以如果你的接口定义换成AsyncHandler<Void>:

interface A {
    public void verifyCredentials(JsonObject credentials, AsyncHandler<Void> handler);
}

模拟方式和上面完全一致,只需要把代码里的Handler<AsyncResult<Void>>替换成AsyncHandler<Void>即可,逻辑没有任何变化。

使用参数捕获

如果需要验证传入verifyCredentials的参数(比如credentials),或者需要手动触发捕获到的Handler,可以用Mockito的ArgumentCaptor。

捕获并验证参数

@Test
public void testCaptureCredentials(TestContext context) {
    // 创建对应类型的参数捕获器
    ArgumentCaptor<JsonObject> credentialsCaptor = ArgumentCaptor.forClass(JsonObject.class);
    ArgumentCaptor<Handler<AsyncResult<Void>>> handlerCaptor = ArgumentCaptor.forClass(Handler.class);

    // 调用待测试方法
    JsonObject testCredentials = new JsonObject().put("user", "salman");
    sampleObject.verifyCredentials(testCredentials, ar -> {
        context.completeNow();
    });

    // 捕获调用时传入的参数
    Mockito.verify(sampleObject).verifyCredentials(
        credentialsCaptor.capture(), 
        handlerCaptor.capture()
    );

    // 验证捕获到的参数是否符合预期
    JsonObject capturedCredentials = credentialsCaptor.getValue();
    context.assertEquals("salman", capturedCredentials.getString("user"));

    // 也可以手动触发捕获到的Handler,模拟异步结果
    Handler<AsyncResult<Void>> capturedHandler = handlerCaptor.getValue();
    capturedHandler.handle(Future.succeededFuture());
}

内容的提问来源于stack exchange,提问作者Shaikh Salman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:31:59