Mockito单元测试中when(..)服务方法存根不生效问题排查
为什么Mockito存根不生效?真实服务被调用的原因及解决办法
核心原因:Spring上下文覆盖了Mock对象
你使用了@SpringBootTest注解,该注解会启动完整的Spring应用上下文。此时Ar11Application作为标注@SpringBootApplication的类,会被Spring自动实例化,其内部@Autowired的ar11ApplicationService会被注入真实的Ar11ApplicationServiceImpl实例。你通过@InjectMocks创建的测试用Ar11Application实例,会被Spring容器中的实例覆盖,导致run方法调用的是真实服务而非mock对象。
额外问题:JUnit注解冲突
测试类混合使用了@RunWith(MockitoJUnitRunner.class)(JUnit4运行器)和@ExtendWith(MockitoExtension.class)(JUnit5扩展),属于冗余配置且可能引发冲突。由于你使用了JUnit5的@BeforeEach和org.junit.jupiter.api.Assertions,应当移除@RunWith注解。
方案一:使用@SpringBootTest + @MockBean(推荐,保留Spring上下文)
这种方式让Spring将mock服务替换容器中的真实实现,同时保留Spring自动配置(如@Value属性注入):
@SpringBootTest @ExtendWith(MockitoExtension.class) class Ar11ApplicationTest { // 用@MockBean替代@Mock,Spring会将该mock实例注入容器 @MockBean Ar11ApplicationService ar11ApplicationService; @MockBean EmailService emailService; // 直接@Autowired获取Spring管理的Ar11Application实例,自动注入mock服务 @Autowired Ar11Application ar11Application; @BeforeEach void setUp() throws Exception { Mockito.when(ar11ApplicationService.processEligibleRecords( Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyString())) .thenReturn(new Ar11ResultBean()); } @Test void main() throws Exception { org.junit.jupiter.api.Assertions.assertDoesNotThrow( () -> ar11Application.run(new String[] {}) ); } }
方案二:纯Mockito测试(不加载Spring上下文)
若无需Spring自动配置,仅测试Ar11Application的逻辑,可移除@SpringBootTest,手动设置@Value属性值:
@ExtendWith(MockitoExtension.class) class Ar11ApplicationTest { @Mock Ar11ApplicationService ar11ApplicationService; @Mock EmailService emailService; @InjectMocks Ar11Application ar11Application; @BeforeEach void setUp() throws Exception { // 手动设置@Value注入的属性值(纯Mockito不处理@Value) ReflectionTestUtils.setField(ar11Application, "eligibleFilename", "test-eligible.txt"); ReflectionTestUtils.setField(ar11Application, "newFilenamePrefix", "test-new-"); ReflectionTestUtils.setField(ar11Application, "sftpUserName", "test-user"); ReflectionTestUtils.setField(ar11Application, "sftpPrivateKeyPath", "/test/path"); ReflectionTestUtils.setField(ar11Application, "sftpPrivateKeyPassphrase", "test-pass"); ReflectionTestUtils.setField(ar11Application, "sftpHost", "test-host"); ReflectionTestUtils.setField(ar11Application, "sftpPort", 22); ReflectionTestUtils.setField(ar11Application, "sourceDir", "/test/source"); ReflectionTestUtils.setField(ar11Application, "remoteDir", "/test/remote"); // 存根设置不变 Mockito.when(ar11ApplicationService.processEligibleRecords( Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyString())) .thenReturn(new Ar11ResultBean()); } @Test void main() throws Exception { org.junit.jupiter.api.Assertions.assertDoesNotThrow( () -> ar11Application.run(new String[] {}) ); } }
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

