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

PowerMockito测试调用Timer.scheduleAtFixedRate方法时报NullPointerException

异常触发原因

直接原因:dateStart成员变量未初始化

你代码中的DailyReminder类的dateStart字段仅做了声明,没有赋值,默认值为null。在执行timer.scheduleAtFixedRate(task, dateStart, fixedDuration.toMillis())时,Timer的scheduleAtFixedRate方法要求第二个参数(首次执行时间)非空,传入null会直接抛出NullPointerException。
你看到异常栈指向dailyReminder.remind()这行,是因为这是测试代码中触发异常的调用入口,并非dailyReminder本身为空,这也是你验证dailyReminder非空但依然抛出NPE的核心原因。

其他潜在问题

  • 测试框架注解混用:你同时使用了JUnit4的@RunWith(PowerMockRunner.class)和JUnit5(Jupiter)的@BeforeEach、@Test注解,版本不兼容会导致setUp方法不执行,进一步加剧变量初始化问题。
  • 无效的@InjectMocks注解:你在setUp方法中手动实例化了DailyReminder的匿名子类,覆盖了@InjectMocks生成的实例,该注解完全失效,且手动创建的实例中user、dateStart等字段都没有初始化。
修复方案
  1. 给dateStart赋值:可以通过反射给测试用的DailyReminder实例的dateStart字段注入有效值,示例代码:
@BeforeEach
public void setUp() throws NoSuchFieldException, IllegalAccessException {
    // 原有逻辑不变
    TimerTask task = new MyTask(user);
    mockTask = mock(task.getClass());

    dailyReminder = new DailyReminder() {
        @Override
        public Timer createTimer() {
            return mockTimer;
        }

        @Override
        public TimerTask createTask() {
            return mockTask;
        }
    };
    // 新增:给dateStart赋值
    Field dateStartField = DailyReminder.class.getDeclaredField("dateStart");
    dateStartField.setAccessible(true);
    dateStartField.set(dailyReminder, new Date());
}
  1. 统一测试框架版本:如果使用JUnit4,将@BeforeEach改为@Before,@Test导入org.junit.Test;如果使用JUnit5,调整PowerMock依赖为支持JUnit5的版本,替换对应的运行器配置。
  2. 移除冗余的@InjectMocks注解,避免混淆。

内容的提问来源于stack exchange,提问作者Ülephaze

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 04:36:03