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

Spring Boot单元测试报错:EmpresaRepository为Null致测试失败

测试方法执行失败:NullPointerException问题排查与解决

报错信息

java.lang.NullPointerException: Cannot invoke "com.priserp.springapipeta.repository.EmpresaRepository.findAll()" because "this.empresaRepository" is null

报错堆栈:

at com.priserp.springapipeta.service.EmpresaService.getAllEmpresas(EmpresaService.java:53)
at com.priserp.springapipeta.unit.service.EmpresaServiceTest.should_Return_All_Empresas(EmpresaServiceTest.java:66)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

服务类代码

@Service
public class EmpresaService {

    private final EmpresaRepository empresaRepository;

    public List<Empresa> getAllEmpresas() {
        return empresaRepository.findAll();
    }

}

@Repository
public interface EmpresaRepository extends JpaRepository<Empresa, Long> {
    Optional<Empresa> findByRazaoSocial(String name);
    Optional<Empresa> findByCnpj(String cnpj);
}

测试类代码

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = PetaApiApplication.class)
class EmpresaServiceTest {
    @Mock
    EmpresaRepository empresaRepository;

    @InjectMocks
    EmpresaService empresaService = new EmpresaService(empresaRepository);

    private final List<Empresa> empresas = new ArrayList<>();

    @Test
    public void should_Return_All_Empresas() {
        Empresa empresa1 = new Empresa(1L, "EMPRESA 1", "12345678");
        Empresa empresa2 = new Empresa(2L, "EMPRESA 2", "456");
        empresas.add(empresa1);
        empresas.add(empresa2);    
        when(empresaRepository.findAll()).thenReturn(empresas);

        List<Empresa> foundEmpresas = this.empresaService.getAllEmpresas();

        assertNotEquals(null, foundEmpresas);

        assertEquals("EMPRESA 1", foundEmpresas.get(0).getRazaoSocial());

        System.out.println(foundEmpresas.size());
        System.out.println(empresas.size());

    }

}

问题原因与修复方案

核心问题

  1. 服务类缺少构造函数:EmpresaService中声明了final修饰的empresaRepository,但没有提供构造函数,Spring无法通过构造注入的方式为其赋值,导致运行时repository为null。
  2. 测试类注解冲突:同时使用@RunWith(MockitoJUnitRunner.class)和@SpringBootTest会导致上下文混乱——前者用于纯Mockito单元测试(无需启动Spring上下文),后者会启动完整的Spring应用上下文,两者混用会破坏依赖注入逻辑。
  3. 手动实例化与注解冲突:同时使用@InjectMocks和手动new EmpresaService(empresaRepository),会导致Mockito的注入逻辑失效。

修复步骤

1. 修复服务类,添加构造函数

为EmpresaService添加构造函数,让Spring能够完成依赖注入:

@Service
public class EmpresaService {

    private final EmpresaRepository empresaRepository;

    // 添加构造函数用于依赖注入
    public EmpresaService(EmpresaRepository empresaRepository) {
        this.empresaRepository = empresaRepository;
    }

    public List<Empresa> getAllEmpresas() {
        return empresaRepository.findAll();
    }

}

2. 调整测试类(二选一)

方案一:纯Mockito单元测试(推荐)

去掉@SpringBootTest,用纯Mockito进行单元测试,无需启动Spring上下文:

@RunWith(MockitoJUnitRunner.class)
class EmpresaServiceTest {
    @Mock
    EmpresaRepository empresaRepository;

    @InjectMocks
    EmpresaService empresaService; // 无需手动new,@InjectMocks会自动创建实例并注入Mock

    @Test
    public void should_Return_All_Empresas() {
        // 准备测试数据
        List<Empresa> empresas = new ArrayList<>();
        Empresa empresa1 = new Empresa(1L, "EMPRESA 1", "12345678");
        Empresa empresa2 = new Empresa(2L, "EMPRESA 2", "456");
        empresas.add(empresa1);
        empresas.add(empresa2);    

        // Mock Repository行为
        when(empresaRepository.findAll()).thenReturn(empresas);

        // 调用服务方法
        List<Empresa> foundEmpresas = empresaService.getAllEmpresas();

        // 断言验证
        assertNotNull(foundEmpresas);
        assertEquals(2, foundEmpresas.size());
        assertEquals("EMPRESA 1", foundEmpresas.get(0).getRazaoSocial());
    }
}
方案二:Spring Boot集成测试

如果需要启动Spring上下文进行集成测试,使用@MockBean替换@Mock和@InjectMocks:

@SpringBootTest
class EmpresaServiceTest {
    @MockBean
    EmpresaRepository empresaRepository;

    @Autowired
    EmpresaService empresaService;

    @Test
    public void should_Return_All_Empresas() {
        List<Empresa> empresas = new ArrayList<>();
        Empresa empresa1 = new Empresa(1L, "EMPRESA 1", "12345678");
        Empresa empresa2 = new Empresa(2L, "EMPRESA 2", "456");
        empresas.add(empresa1);
        empresas.add(empresa2);    

        when(empresaRepository.findAll()).thenReturn(empresas);

        List<Empresa> foundEmpresas = empresaService.getAllEmpresas();

        assertNotNull(foundEmpresas);
        assertEquals(2, foundEmpresas.size());
        assertEquals("EMPRESA 1", foundEmpresas.get(0).getRazaoSocial());
    }
}

内容的提问来源于stack exchange,提问作者Gilmar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:25:58