如何用Mockito覆盖代码else分支(#def)提升Sonar代码覆盖率?
解决单元测试覆盖#else分支的问题
你的问题出在只mock了List的isEmpty()方法,但没把这个mock的List关联到代码里的result.result()返回值上。代码里的mobileList来自getSomeDetails返回的Future的执行结果,所以得从根源上让这个Future返回成功的Result,且Result携带非空列表。
具体步骤如下:
模拟成功的Result对象
创建一个Result实例,让它的succeeded()返回true,同时让result()返回一个非空列表(用真实列表比mock List更简单):Result<List<String>> mockResult = Mockito.mock(Result.class); // 标记Result为成功状态 Mockito.when(mockResult.succeeded()).thenReturn(true); // 准备一个非空列表,直接用真实实例即可 List<String> nonEmptyMobileList = Arrays.asList("13800138000", "13900139000"); // 让Result返回这个非空列表 Mockito.when(mockResult.result()).thenReturn(nonEmptyMobileList);模拟getSomeDetails返回的Future
让getSomeDetails方法返回的Future在触发onComplete时,把上面的mockResult传入回调:// 假设你的业务类是MyService,用spy保留原有逻辑或直接mock MyService myService = Mockito.spy(new MyService()); Future<List<String>> mockFuture = Mockito.mock(Future.class); // 模拟Future的onComplete行为:调用回调时直接传入mockResult Mockito.doAnswer(invocation -> { // 获取传入的回调函数 Function<Result<List<String>>, Void> callback = invocation.getArgument(0); // 执行回调,传入成功的Result callback.apply(mockResult); return null; }).when(mockFuture).onComplete(Mockito.any()); // 让getSomeDetails返回这个mockFuture Mockito.when(myService.getSomeDetails(Mockito.anyString(), Mockito.any(User.class))) .thenReturn(mockFuture);执行测试并验证
调用你的业务方法后,代码会触发onComplete回调,此时mobileList.isEmpty()会返回false,自然会走到标记为#def的else分支,完成代码覆盖。
如果坚持要用mock的List,只需要把上面的nonEmptyMobileList换成你之前mock的List即可,但真实列表的写法更简洁,不容易出错。
内容的提问来源于stack exchange,提问作者Stunner
相关产品推荐
相关产品推荐

