Mockito模拟Getter返回Null无效,JUnit5测试覆盖率问题求助
问题分析
你的测试没覆盖到目标分支,核心原因是业务代码里的doSomething()方法是自己new ResDTO()创建实例,而测试中用@MockBean声明的ResDTO是Spring容器管理的实例,和业务代码里的实例完全无关,所以你对mock对象的配置根本不会生效。
另外测试代码里还有两个小问题:
@Test方法不能是private,必须改为public- 你试图mock
setSellerList的逻辑完全没必要,因为目标是让getSellerList()返回null
解决方案
方案1:抽离ResDTO创建逻辑(推荐)
修改业务代码,把ResDTO的创建逻辑抽成一个可被mock的方法,这样测试时可以通过Mockito Spy来替换这个方法的返回值:
修改后的业务代码
public class MyClass { public void myMethod() { ResDTO resDto = doSomething(); } private ResDTO doSomething() { ResDTO resDto = createResDTO(); // 调用抽离的方法 // ... List<SellerDTO> editSellerListRes = editSellerList(resDto.getSellerList()); resDto.setSellerList(editSellerListRes); return resDto; } // 抽离的创建方法,用protected方便测试mock protected ResDTO createResDTO() { return new ResDTO(); } private List<SellerDTO> editSellerList(List<SellerDTO> inSellerList) { if (inSellerList == null || inSellerList.size() == 0) { System.out.println("I need to have this part covered in the test"); return new ArrayList<>(); } // 补充原方法的其他逻辑,比如非空时的处理 return inSellerList; } }
对应的测试代码
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; import static org.mockito.Mockito.when; // 用MockitoExtension代替SpringBootTest,更轻量,无需启动Spring容器 @ExtendWith(MockitoExtension.class) class MyClassTest { @Spy private MyClass myClass; // Spy原对象,允许部分mock @Mock private ResDTO resDto; // 直接mock ResDTO,无需@MockBean @Test public void testEditSellerListWithNullInput() { // 让createResDTO方法返回我们的mock对象 when(myClass.createResDTO()).thenReturn(resDto); // 配置mock对象的getSellerList返回null when(resDto.getSellerList()).thenReturn(null); myClass.myMethod(); // 调用入口方法,触发doSomething逻辑 // 可添加断言验证逻辑,比如验证返回结果是否符合预期 } }
方案2:不修改业务代码(直接测试private方法)
如果不能修改业务代码,可通过反射直接调用private的editSellerList方法来覆盖目标分支:
测试代码示例
import org.junit.jupiter.api.Test; import java.lang.reflect.Method; import java.util.List; import static org.junit.jupiter.api.Assertions.*; class MyClassTest { @Test public void testEditSellerListWithNull() throws Exception { MyClass myClass = new MyClass(); // 获取private的editSellerList方法 Method method = MyClass.class.getDeclaredMethod("editSellerList", List.class); method.setAccessible(true); // 允许访问private方法 // 传入null调用方法 List<SellerDTO> result = (List<SellerDTO>) method.invoke(myClass, (List<SellerDTO>) null); // 断言结果是空列表 assertNotNull(result); assertTrue(result.isEmpty()); } }
这种方式直接验证editSellerList的逻辑,但会跳过上层doSomething的调用流程,适合只能单独验证该方法的场景。
内容的提问来源于stack exchange,提问作者demiglace
相关产品推荐
相关产品推荐

