如何用assertSame/assertEquals测试Mockito中void方法?解决Sonar/PMD断言违规
解决Mockito测试Void方法时的Sonar/PMD规则违规问题
你遇到的问题很常见——静态代码检查工具(比如Sonar或PMD)要求JUnit测试必须包含assert()或fail()语句,而单纯用verify()验证交互的测试会被判定违规。针对void方法,我们可以通过捕获方法调用的参数并断言参数属性的方式,既验证业务逻辑的正确性,又满足代码检查规则。
核心思路
因为void方法没有返回值,我们需要验证它的「副作用」:比如调用依赖组件(这里是dyDBDAO.save())时传入的参数是否符合预期。使用Mockito的ArgumentCaptor可以捕获save()方法接收的Detail对象,然后通过assertEquals或assertSame断言对象的属性是否正确。
修改后的测试代码
下面是调整后的testUpdate()方法,加入了参数捕获和断言:
@Test public void testUpdate() { // 静态类Mock配置 PowerMockito.mockStatic(Places.class); given(Places.getPlace()) .willReturn(Places.getPlace("UH")) // 匹配业务类中getPlace()的逻辑 .willReturn(null); // 两次调用update方法(修正原代码笔误:syncStatus应为update) myServiceImpl.update(); myServiceImpl.update(); // 1. 定义ArgumentCaptor捕获Detail类型的参数 ArgumentCaptor<Detail> detailCaptor = ArgumentCaptor.forClass(Detail.class); // 2. 验证dyDBDAO.save被调用2次,并捕获每次的参数 verify(dyDBDAO, times(2)).save(detailCaptor.capture()); // 3. 获取捕获的所有参数 List<Detail> capturedDetails = detailCaptor.getAllValues(); // 4. 断言第一次调用的Detail对象的place属性是"UH" assertEquals("UH", capturedDetails.get(0).getPlace()); // 5. 断言第二次调用的Detail对象的place属性是"DH"(对应业务类逻辑:Places.getPlace()为null时返回PlacesUtil.getName("DH")) assertEquals("DH", capturedDetails.get(1).getPlace()); // 可选:补充断言其他属性,确保业务逻辑完整 assertEquals("blah", capturedDetails.get(0).getName()); assertEquals("fsdfsdfdsf", capturedDetails.get(0).getDesc()); }
关键步骤解释
- ArgumentCaptor初始化:
ArgumentCaptor.forClass(Detail.class)创建一个用于捕获Detail类型参数的捕获器。 - 捕获参数:在
verify()方法中传入detailCaptor.capture(),Mockito会自动记录每次save()调用时传入的参数。 - 断言参数属性:通过
getAllValues()获取所有捕获的参数列表,然后对每个参数的属性(比如place、name)进行断言,这样就满足了Sonar/PMD对assert()语句的要求。
额外注意点
- 原测试代码里的
myServiceImpl.syncStatus()是笔误,需要改为myServiceImpl.update(),和业务类中定义的方法保持一致。 - 确保
Detail类有对应的getPlace()、getName()、getDesc()getter方法,否则无法正常断言属性。 - 可以根据业务需求添加更多断言,比如验证
desc属性或其他字段,让测试覆盖更全面。
这样修改后,你的测试既有交互验证(verify()),又有结果断言(assertEquals()),既能验证业务逻辑的正确性,又能通过Sonar/PMD的规则检查。
内容的提问来源于stack exchange,提问作者Learner
相关产品推荐
相关产品推荐

