You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit测试触发java.lang.StackOverflowError求解决 | 单元测试新手求助

嘿,我看到你刚接触单元测试,遇到了StackOverflowError的问题,咱们一步步拆解解决,再聊聊测试用例的设计~

一、StackOverflowError的核心原因

你的测试类里有两个私有方法犯了无限递归的错误,直接导致栈溢出:

  • getDayWithNulls()方法内部第一行就调用了getDayWithNulls().setTrainings(null),这会不断调用自身,没有终止条件,最终耗尽栈空间。
  • expectedDayWithAddedTrainingToNulls()也是同样的问题,方法内一直在递归调用自己,根本无法创建出有效的Day实例。

修正后的方法代码

把这两个方法改成先创建Day实例,再设置属性:

private Day getDayWithNulls() {
    Day day = new Day();
    day.setTrainings(null);
    day.setMeasurements(null);
    day.setTrainingCycles(null);
    day.setDiets(null);
    day.setMeals(null);
    day.setLocalDate(LocalDate.now());
    return day;
}

private Day expectedDayWithAddedTrainingToNulls() {
    Day day = new Day();
    day.setTrainings(Collections.singletonList(getTrainingForTest()));
    day.setMeasurements(null);
    day.setTrainingCycles(null);
    day.setDiets(null);
    day.setMeals(null);
    day.setLocalDate(LocalDate.now());
    return day;
}

二、测试类的其他关键修复

  1. Mock方法行为未定义
    你的addTraining方法依赖getActivityBoardDay(localDate, userId)获取Day对象,但你没有用Mockito定义这个方法的返回值,运行时会返回null,进而触发NullPointerException。需要在测试方法里补充Mock行为:
@Test
public void addTraining_WhenTrainingsIsNull_AddsSuccessfully() {
    // 构造测试用的Day对象
    Day testDay = getDayWithNulls();
    // 定义Mock方法的返回值
    when(databaseControllerMock.getActivityBoardDay(LocalDate.now(), userId)).thenReturn(testDay);
    
    // 执行待测试方法
    Training testTraining = getTrainingForTest();
    activitiesService.addTraining(userId, testTraining, LocalDate.now());
    
    // 验证结果:注意要确保Day类正确实现了equals/hashCode,否则比较具体属性
    Assert.assertEquals(Collections.singletonList(testTraining), testDay.getTrainings());
}
  1. @After方法的冗余操作
    你的@After方法里的操作完全没必要,因为JUnit会在每次测试后自动清理测试上下文,@Before方法会重新创建activitiesService实例。可以直接删掉这个@After方法,或者改成重置Mock:
@After
public void tearDown() throws Exception {
    reset(databaseControllerMock);
}

三、关于测试用例的设计

你计划的三个测试用例非常合理,刚好覆盖addTraining方法的所有分支逻辑:

  • 测试场景1:Day的trainings列表为null时添加训练(你当前的测试)
  • 测试场景2:Day的trainings列表为空(empty)时添加训练
  • 测试场景3:Day的trainings列表已有训练时,添加新训练

每个场景单独写一个测试方法,这样能清晰覆盖所有代码路径,也方便定位问题~

内容的提问来源于stack exchange,提问作者D.Zet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:33:30