使用 ArgumentCaptor 对异步回调的方法进行单元测试
背景
博主在近期工作中,对模块进行异步化修改,主要进行RPC调用时,不再进行同步等待。对代码完成修改后,需要进行单元测试覆盖,其中就包括了异步回调的单元测试覆盖。
由于涉及业务代码,这里对场景进行简化,即需要对异步回调的场景进行单元测试。这里通过代码模拟一个简单的场景:首先是有一个接口类IAsyncHanlder的接口,定义了onSucess方法。
public interface IAsyncHandler {
void onSuccess(String result);
}
RpcService模拟提供rpc远程调用,完成后调用传入的接口实现类的onSuccess方法。
@Component
public class RpcService {
public void doHandle(IAsyncHandler handler) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// rpc invoke
String result = "true";
handler.onSuccess(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
业务场景方面,AsyncService类对外提供asyncSend方法,调用该方法之后,AsyncService会先进行一次RPC调用,再根据RPC异步回调的结果,决定使用使用PushService类提供的method1或method2。场景比较简单,具体代码如下:
@Component
public class AsyncService {
private static final String TRUE = "true";
private RpcService rpcService;
private PushService pushService;
@Autowired
public AsyncService(RpcService rpcService, PushService pushService) {
this.rpcService = rpcService;
this.pushService = pushService;
}
// 对外提供方法调用
public void asyncSend() {
// 根据远程调用结果,决定使用不同的方法
rpcService.doHandle(new IAsyncHandler() {
@Override
public void onSuccess(String result) {
if (TRUE.equals(result)) {
// do somethings ...
pushService.method1();
} else {
// do somethings ...
pushService.method2();
}
}
});
}
}
上面即为完整的场景,下面将对asyncSend方法进行单元测试覆盖。
使用 ArgumentCaptor
思路:我们可以利用ArgumentCaptor捕捉到传递给RpcServicde的接口实现类,之后为手动调用接口实现类的onSuccess方法,模拟异步回调的场景。代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {AsyncService.class})
public class AsyncServiceTest {
@MockBean
private RpcService rpcService;
@MockBean
private PushService pushService;
@Autowired
private AsyncService asyncService;
@Test
public void testAsyncSend_method1() {
asyncService.asyncSend();
// 捕获接口的实现类,即异步回调结果调用的对象
ArgumentCaptor<IAsyncHandler> argumentCaptor = ArgumentCaptor.forClass(IAsyncHandler.class);
Mockito.verify(rpcService).doHandle(argumentCaptor.capture());
// 手动调用处理异步回调的对象,模拟异步回调的结果
IAsyncHandler asyncHandler = argumentCaptor.getValue();
asyncHandler.onSuccess("true");
// 对异步回调的结果进行测试覆盖
Mockito.verify(pushService).method1();
Mockito.verify(pushService, Mockito.never()).method2();
}
@Test
public void testAsyncSend_method2() {
// 捕获接口的实现类,即异步回调结果调用的对象
asyncService.asyncSend();
ArgumentCaptor<IAsyncHandler> argumentCaptor = ArgumentCaptor.forClass(IAsyncHandler.class);
Mockito.verify(rpcService).doHandle(argumentCaptor.capture());
// 手动调用处理异步回调的对象,模拟异步回调的结果
IAsyncHandler asyncHandler = argumentCaptor.getValue();
asyncHandler.onSuccess("false");
// 对异步回调的结果进行测试覆盖
Mockito.verify(pushService).method2();
Mockito.verify(pushService, Mockito.never()).method1();
}
}
总结
通过利用ArgumentCaptor捕捉到异步回调时会调用的类,手动给调用类进行赋值,进行异步回调场景的测试覆盖。
本文介绍了如何在Java中对使用异步回调的方法进行单元测试。通过ArgumentCaptor捕获回调接口,模拟RPC调用后的异步响应,以确保测试覆盖率。
542

被折叠的 条评论
为什么被折叠?



