1. 概述
在这篇简短的教程中,我们将重点介绍如何使用流行的测试框架 Mockito 来 测试回调函数(Callbacks)。
我们会讲解两种解决方案:
✅ 第一种是使用 ArgumentCaptor
抓取回调对象
✅ 第二种是使用更直观的 doAnswer()
方法
如果你对 Mockito 的使用还不太熟悉,可以查看我们整理的 Mockito 系列文章。
2. 回调函数简介
回调(Callback)是一种代码片段,作为参数传递给某个方法,并在特定时机被调用执行。
回调可以是同步的(立即执行),也可以是异步的(稍后执行)。
最常见的使用场景是 服务调用后处理响应结果。
在本教程中,我们使用如下接口作为被测对象的依赖(协作对象):
public interface Service {
void doAction(String request, Callback<Response> callback);
}
其中,Callback
接口定义如下,用于处理响应:
public interface Callback<T> {
void reply(T response);
}
2.1. 一个简单的服务示例
我们还会使用一个简单的服务示例,展示如何传递并调用回调函数:
public void doAction() {
service.doAction("our-request", new Callback<Response>() {
@Override
public void reply(Response response) {
handleResponse(response);
}
});
}
handleResponse
方法会检查响应是否有效,并在有效时设置数据:
private void handleResponse(Response response) {
if (response.isValid()) {
response.setData(new Data("Successful data response"));
}
}
为了清晰起见,这里没有使用 Lambda 表达式,但你也可以这样写得更简洁:
service.doAction("our-request", response -> handleResponse(response));
想了解更多关于 Lambda 的内容?可以看 这篇文章。
3. 使用 ArgumentCaptor
捕获回调
下面来看如何使用 Mockito 的 ArgumentCaptor
来 捕获并验证回调对象:
@Test
public void givenServiceWithValidResponse_whenCallbackReceived_thenProcessed() {
ActionHandler handler = new ActionHandler(service);
handler.doAction();
verify(service).doAction(anyString(), callbackCaptor.capture());
Callback<Response> callback = callbackCaptor.getValue();
Response response = new Response();
callback.reply(response);
String expectedMessage = "Successful data response";
Data data = response.getData();
assertEquals(
"Should receive a successful message: ",
expectedMessage, data.getMessage());
}
📌 步骤解析:
- 创建
ActionHandler
并调用其doAction()
方法(内部会调用服务的回调) - 验证
service.doAction()
是否被调用,并使用callbackCaptor.capture()
捕获回调对象 - 获取捕获的回调对象,手动调用
reply()
方法 - 最后断言返回结果是否符合预期
⚠️ 注意:这种方式适合你想手动控制回调的执行时机和参数。
4. 使用 doAnswer()
方法模拟回调
另一种常见的方法是使用 Mockito 的 doAnswer()
和 Answer
对象来 模拟回调行为:
@Test
public void givenServiceWithInvalidResponse_whenCallbackReceived_thenNotProcessed() {
Response response = new Response();
response.setIsValid(false);
doAnswer((Answer<Void>) invocation -> {
Callback<Response> callback = invocation.getArgument(1);
callback.reply(response);
Data data = response.getData();
assertNull("No data in invalid response: ", data);
return null;
}).when(service)
.doAction(anyString(), any(Callback.class));
ActionHandler handler = new ActionHandler(service);
handler.doAction();
}
📌 步骤解析:
- 先创建一个无效的
Response
对象 - 使用
doAnswer()
拦截doAction()
的调用,获取参数中的回调对象 - 手动调用
reply()
,并验证返回结果是否符合预期 - 最后执行
handler.doAction()
,触发整个流程
✅ 这种方式适合你希望在模拟方法调用时自动触发回调逻辑的场景。
想了解更多关于如何模拟 void 方法?可以参考 这篇文章。
5. 总结
本篇文章我们介绍了两种在 Mockito 中测试回调函数的方式:
- 使用
ArgumentCaptor
捕获回调对象,手动触发执行 - 使用
doAnswer()
模拟回调调用过程
两种方式各有适用场景,灵活运用可以让你的单元测试更强大、更可控。
📌 本文所有示例代码均可在 GitHub 项目 中找到。