如何测试依赖其他服务的Spring服务?JUnit5遇栈溢出
解决单元测试中的StackOverflowError问题
问题根源
从错误栈可以明确,栈溢出是因为User和Kelompok实体类的toString()方法发生循环递归调用:User.toString()中引用了Kelompok对象,而Kelompok.toString()又反过来引用了User对象,无限循环调用最终耗尽栈内存抛出错误。
解决方案
1. 修改实体类的toString方法
调整User和Kelompok的toString()实现,避免互相引用整个对象,只保留对方的基础属性(比如ID):
- Kelompok类的toString修改示例:
@Override public String toString() { return "Kelompok{" + "id=" + id + ", nik='" + nik + '\'' + // 仅引用User的ID,而非整个User对象 ", userId=" + (user != null ? user.getId() : null) + '}'; }
- User类的toString修改示例:
@Override public String toString() { return "User{" + "id=" + id + // 若User关联Kelompok集合,仅保留ID列表或直接移除该属性 ", kelompokIds=" + (kelompoks != null ? kelompoks.stream().map(Kelompok::getId).collect(Collectors.toList()) : null) + '}'; }
2. 优化测试类(可选,提升测试效率)
当前测试使用@SpringBootTest加载完整Spring上下文,可改用更轻量的Mockito扩展,无需加载完整Spring环境:
@ExtendWith(MockitoExtension.class) public class KelompokServiceTest { private final EasyRandom EASY_RANDOM = new EasyRandom(); private KelompokDTO kelompokDTO; // 注入被测试对象,自动装配mock依赖 @InjectMocks KelompokService kelompokService; // 模拟UserService依赖 @Mock private UserService userService; // 模拟KelompokRepository依赖 @Mock private KelompokRepository kelompokRepository; @BeforeEach void setUp() { kelompokDTO = EASY_RANDOM.nextObject(KelompokDTO.class); } @Test void testSave_Success() { User user = EASY_RANDOM.nextObject(User.class); when(userService.findById(kelompokDTO.getIdUser())).thenReturn(user); Kelompok expectedKelompok = new Kelompok(); expectedKelompok.setUser(user); expectedKelompok.setNik(kelompokDTO.getNik()); when(kelompokRepository.save(any(Kelompok.class))).thenReturn(expectedKelompok); Kelompok result = kelompokService.save(kelompokDTO); assertEquals(expectedKelompok.getNik(), result.getNik()); assertEquals(expectedKelompok.getUser().getId(), result.getUser().getId()); } }
该修改让测试启动更快,也更符合单元测试“隔离依赖”的核心原则。
内容的提问来源于stack exchange,提问作者Syan
相关产品推荐
相关产品推荐

