Spring Boot单元测试Mock Repository无效,Service调用真实Repo报错求助
解决Spring Boot Service单元测试中Mock Repository未生效的问题
嘿,我帮你排查下问题,你现在的Mock没生效主要是配置冲突加上拼写错误在拖后腿,咱们一步步来解决:
1. 先修正致命的拼写错误
你的代码里有两处拼写错误,这会导致Mockito根本找不到要Mock的Repository:
- 类名:
UserRepostiory→UserRepository(少了个t) - 变量名:
userRepostitory→userRepository(同样少了个t)
2. 选择正确的测试模式(二选一)
你现在的测试混合了「Spring集成测试」和「纯Mockito单元测试」的配置,这是Mock失效的核心原因。根据你的需求(单元测试Service),推荐下面两种方案:
方案一:纯Mockito单元测试(推荐,轻量快速)
单元测试不需要加载整个Spring上下文,只用Mockito的扩展就能完成。去掉所有Spring相关的注解,只保留@ExtendWith(MockitoExtension.class):
@ExtendWith(MockitoExtension.class) public class UserTest{ @InjectMocks private UserServiceImpl userService; @Mock private UserRepository userRepository; // 已修正拼写 // 注意:Junit5用@BeforeEach替代Junit4的@Before @BeforeEach public void setUp() { User user = new User(1L, "email@email", "name"); when(userRepository.findById(1L)).thenReturn(Optional.of(user)); // 已修正拼写 } @Test public void findUserByIdReturnsUser() { User user = userService.getById(1L); assertEquals(1L, user.getId()); } }
为什么原来的配置不行?
@SpringBootTest会强制加载整个Spring应用上下文,这时候Spring会自行创建UserServiceImpl的实例,而不是用Mockito的@InjectMocks来注入Mock的Repository,所以实际调用的是真实的Repository(测试环境的数据库大概率是空的,所以找不到用户)。- 同时使用
@ExtendWith(SpringExtension.class)和@ExtendWith(MockitoExtension.class)会造成依赖注入的冲突,Spring的扩展会优先接管,导致Mockito的Mock无法被注入到Service实例中。
方案二:Spring集成测试(如果需要Spring上下文)
如果你因为某些原因必须加载Spring上下文(比如需要用到Spring的其他Bean或配置),那应该用@MockBean替代@Mock和@InjectMocks,这样Spring会把Mock的Repository注册到上下文里,替换掉真实的Bean:
@SpringBootTest @ActiveProfiles("test") public class UserTest{ @Autowired private UserServiceImpl userService; @MockBean private UserRepository userRepository; // 已修正拼写 @BeforeEach public void setUp() { User user = new User(1L, "email@email", "name"); when(userRepository.findById(1L)).thenReturn(Optional.of(user)); } @Test public void findUserByIdReturnsUser() { User user = userService.getById(1L); assertEquals(1L, user.getId()); } }
最后总结
- 做Service单元测试优先选纯Mockito方案,不需要加载Spring上下文,测试速度更快,也更符合单元测试的隔离原则。
- 拼写错误很容易被忽略,一定要检查变量名和类名的拼写是否一致,Mockito对名称匹配很严格。
- 如果是集成测试(需要Spring上下文),就用
@SpringBootTest配合@MockBean来替换真实的Repository。
内容的提问来源于stack exchange,提问作者iiiiiiiiiiiiiiiiiiii
相关产品推荐
相关产品推荐

