单元测试单独运行正常,全量运行报Mockito NoSuchMethodError错误
问题根因
报错的核心原因是项目全局依赖的Mockito版本低于3.2.0:MockitoAnnotations.openMocks(Ljava/lang/Object;)Ljava/lang/AutoCloseable;是Mockito 3.2.0版本才新增的API,而Spring Boot测试组件自带的MockitoTestExecutionListener初始化Mock时会默认调用这个新API。
单独运行测试正常是因为单测运行时类路径优先加载了高版本Mockito,运行全量测试时类路径优先级变化,加载了全局低版本Mockito,因此触发方法找不到的错误。
解决方案(无需修改全局依赖版本)
方案1:保留SpringBoot测试环境,调整监听器配置
如果你的测试依赖Spring上下文(比如需要测试Spring @Cacheable 注解实现的缓存逻辑),用这个方案:
import org.springframework.test.context.TestExecutionListeners; import org.mockito.MockitoAnnotations; import org.junit.jupiter.api.BeforeEach; @SpringBootTest // 排除默认的MockitoTestExecutionListener,避免其调用高版本Mockito的API @TestExecutionListeners( mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS, excludeListeners = org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.class ) public class LabelCacheTest { @MockBean private LabelRepository labelRepository; @Autowired // 移除@InjectMocks注解,@MockBean已经会自动注入到Spring管理的LabelServiceImpl实例中 private LabelServiceImpl labelService; // 手动用低版本Mockito兼容的API初始化Mock @BeforeEach public void initMocks() { MockitoAnnotations.initMocks(this); } @Test public void test_for_Cache() { List<LabelDTO> resultFromDatabase = labelService.findAll(); List<LabelDTO> resultFromCache = labelService.findAll(); verify(labelRepository, times(1)).findAllLabels(); assertEquals(resultFromDatabase, resultFromCache); } }
方案2:改用纯Mockito单元测试,避开Spring测试组件的依赖
如果你的测试不需要依赖其他Spring组件,可以用纯Mockito测试,完全避开Spring测试监听器的调用:
import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.Mock; import org.mockito.InjectMocks; // 替换@SpringBootTest,使用纯Mockito扩展 @ExtendWith(MockitoExtension.class) public class LabelCacheTest { // 替换@MockBean为纯Mockito的@Mock注解 @Mock private LabelRepository labelRepository; // 移除@Autowired,@InjectMocks会自动将Mock注入实例 @InjectMocks private LabelServiceImpl labelService; @Test public void test_for_Cache() { // 注意:如果你的缓存是通过Spring @Cacheable实现的,此方案下缓存切面不会生效,需使用方案1 List<LabelDTO> resultFromDatabase = labelService.findAll(); List<LabelDTO> resultFromCache = labelService.findAll(); verify(labelRepository, times(1)).findAllLabels(); assertEquals(resultFromDatabase, resultFromCache); } }
内容的提问来源于stack exchange,提问作者user16979464
相关产品推荐
相关产品推荐

