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

使用Mockito在Service测试中Mock工厂方法遇空指针如何解决?

问题根因
  • 依赖注入失效:ConverterServiceImpl中ConverterFactory是直接硬编码new ConverterFactory()生成的实例,不属于Spring管理的注入依赖,测试类中@Mock的ConverterFactory无法注入到服务类中,服务类运行时始终调用真实的ConverterFactory实例而非Mock对象,这是触发空指针的核心原因。
  • Mock打桩对象错误:测试方法内重新定义了局部变量ConverterFactory converterFactory = mock(ConverterFactory.class),覆盖了类级别@Mock的同名对象,你对局部Mock对象的打桩逻辑完全不会作用到服务类用到的实例上。
  • Mock对象使用错误:WebLinkRequest是Mock对象,直接调用setUrl没有任何作用(Mock对象的非打桩方法默认是空实现),调用webLinkRequest.getUrl()时会返回null,也存在空指针风险。
  • 缺少必要打桩:没有对productConverter.toDeepLink()方法打桩,后续调用该方法时会返回null,导致断言失败。
修复步骤
  1. 改造ConverterServiceImpl,将ConverterFactory改为注入依赖:
@Service
@RequiredArgsConstructor
public class ConverterServiceImpl implements ConverterService {
    // 改为注入的final成员,不要自行new实例
    private final ConverterFactory factory;
    private final WebLinkRepository webLinkRepository;
    private final DeepLinkRepository deepLinkRepository;

    @Override
    public DeepLinkResponse toDeepLink(WebLinkRequest webLinkRequest) {
        WebLink webLink;
        String url = webLinkRequest.getUrl();
        Converter converter = factory.getConverter(url);

        webLink = new WebLink();
        webLink.setUrl(url);
        String convertedUrl = converter.toDeepLink(url);
        webLink.setConvertedUrl(convertedUrl);
        webLinkRepository.save(webLink);

        return new DeepLinkResponse(convertedUrl);
    }
}
  1. 改造测试类,修正打桩逻辑:
@RunWith(MockitoJUnitRunner.class)
public class ConverterServiceImplTest {

    @InjectMocks
    ConverterServiceImpl converterService;

    @Mock
    WebLinkRepository webLinkRepository;
    @Mock
    DeepLinkRepository deepLinkRepository;
    @Mock
    ConverterFactory converterFactory;
    @Mock
    ProductConverter productConverter;
    @Mock
    WebLinkRequest webLinkRequest;

    // 改用@BeforeEach,修正Mock对象的打桩逻辑
    @BeforeEach
    void init(){
        when(webLinkRequest.getUrl()).thenReturn(WEBLINK_ONLY_PRODUCT);
        // 补充productConverter的方法打桩
        when(productConverter.toDeepLink(WEBLINK_ONLY_PRODUCT)).thenReturn("ty://?Page=Product&ContentId=1925865");
    }

    @Test
    public void toDeepLink_only_content_id() {
        // 直接用类级别@Mock的converterFactory打桩,不需要重复创建Mock对象
        when(converterFactory.getConverter(any())).thenReturn(productConverter);

        DeepLinkResponse deepLinkResponse = converterService.toDeepLink(webLinkRequest);
        assertEquals(deepLinkResponse.getUrl(),"ty://?Page=Product&ContentId=1925865");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 06:36:06