如何在Vertx中用Mockito模拟Handler<AsyncResult<Void>>及参数捕获
在Vert.x中使用Mockito模拟Handler<AsyncResult>及相关场景指南
我来一步步帮你搞定Vert.x结合Mockito测试时遇到的这些问题,先从你现有代码里的小问题入手,再依次覆盖模拟Handler、AsyncHandler和参数捕获的场景。
先修复你的基础测试代码
首先你的现有代码里有两个小问题:
- 你要mock的是
A接口,但代码里写了Mockito.mock(C.class),这会导致后续调用方法时出错; 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
相关产品推荐
相关产品推荐

