【Java】异步回调方法进行单元测试

本文介绍了如何在Java中对使用异步回调的方法进行单元测试。通过ArgumentCaptor捕获回调接口,模拟RPC调用后的异步响应,以确保测试覆盖率。

使用 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类提供的method1method2。场景比较简单,具体代码如下:

@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捕捉到异步回调时会调用的类,手动给调用类进行赋值,进行异步回调场景的测试覆盖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值