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等字段都没有初始化。
修复方案
- 给
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()); }
- 统一测试框架版本:如果使用JUnit4,将
@BeforeEach改为@Before,@Test导入org.junit.Test;如果使用JUnit5,调整PowerMock依赖为支持JUnit5的版本,替换对应的运行器配置。 - 移除冗余的
@InjectMocks注解,避免混淆。
内容的提问来源于stack exchange,提问作者Ülephaze
相关产品推荐
相关产品推荐

