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

Junit测试Controller时mock Service内部ClientCrm为空抛空指针异常

问题根因

你在进行Controller单元测试时的Mockito使用逻辑存在错误,导致mock失效、真实Service被调用触发空指针:

  • 你已经用@Mock标注了OfertasConcurrentesService,但又在@BeforeAll里手动执行ofertasService = new OfertasConcurrentesService();,直接把Mockito生成的mock实例覆盖成了真实对象
  • 手动new的OfertasConcurrentesService调用的是无参构造方法,没有传入ClientCrm实例,导致Service内部的clientCrm属性为null
  • 你测试的是Controller层,本来只要mock Service的返回结果即可,完全不需要初始化真实的Service实例,更不需要关心Service内部的Client依赖

修复方案

第一步:给测试类添加Mockito注解支持

在测试类上添加@ExtendWith(MockitoExtension.class)注解(Junit5对应Mockito的扩展),不需要手动初始化Controller和Service实例,Mockito会自动处理@Mock和@InjectMocks的注入逻辑。

第二步:删除@BeforeAll里的手动初始化代码

你手动编写的三行实例化代码完全覆盖了Mockito的注入逻辑,直接删除即可。

第三步:修正后的测试类示例

import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import java.util.Objects;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(MockitoExtension.class) // 新增Mockito扩展支持
class OfertaConcurrenteControllerTest {

    // 测试Controller不需要Mock ClientCrm,可以直接删除该行
    // @Mock
    // private ClientCrm clientCrm;
    
    @Mock
    OfertasConcurrentesService ofertasService ;
    @InjectMocks
    OfertaConcurrenteController ofertasController;

    // 不需要@Autowired,测试时自己构造请求参数即可
    OfertaRequest ofertaRequest;

    @Test
    void testPostOfertaAsync() throws Exception {
        List<Inmueble> listaInmuebles = new ArrayList<>();
        listaInmuebles.add(new Inmueble("a","b","c","s","r","t","u"));
        Oferta oferta = new Oferta((long)266500000,LocalDateTime.of(2017, 2, 13, 15, 56),listaInmuebles);
        CompletableFuture<Oferta> futuro = CompletableFuture.completedFuture(oferta);
        
        ofertaRequest = new OfertaRequest("00457","087945","5642564z","4564","mail@mail.mail");
        when(ofertasService.identificacionOferta(ofertaRequest)).thenReturn(futuro);
        
        // 可补充更具体的断言校验返回结果
        CompletableFuture<ResponseEntity<Oferta>> result = ofertasController.postOfertaAsync(ofertaRequest);
        assert result != null;
        assert Objects.equals(result.get().getBody(), oferta);
    }

    @Test
    void testPropuestaCompra() {
        fail("Not yet implemented");
    }
}

额外说明

如果你后续需要单独测试Service层,再单独mock Service的依赖ClientCrm、EmailService等传入Service的构造方法即可,Controller层测试不需要关心Service内部的实现细节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:39:02