You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mockito模拟Getter返回Null无效,JUnit5测试覆盖率问题求助

问题分析

你的测试没覆盖到目标分支,核心原因是业务代码里的doSomething()方法是自己new ResDTO()创建实例,而测试中用@MockBean声明的ResDTO是Spring容器管理的实例,和业务代码里的实例完全无关,所以你对mock对象的配置根本不会生效。

另外测试代码里还有两个小问题:

  • @Test方法不能是private,必须改为public
  • 你试图mocksetSellerList的逻辑完全没必要,因为目标是让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 00:27:04