使用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,导致断言失败。
修复步骤
- 改造
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); } }
- 改造测试类,修正打桩逻辑:
@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
相关产品推荐
相关产品推荐

