powermockito 测试方法调用时出现 NullPointerException

NullPointerException when powermockito testing method invocation

我刚开始使用 powermockito 进行单元测试,目前我正在尝试测试调用 java.util.Timer.scheduleAtFixedRate 的方法。我尝试 运行 测试但它失败了,并在对象调用方法的行显示 NullPointerException 我想我的对象不为空。这是我的代码,我总结了可能导致问题的部分。

DailyReminderTest.java

@RunWith(PowerMockRunner.class)
@PrepareForTest(DailyReminder.class)
public class DailyReminderTest {

    @InjectMocks
    DailyReminder dailyReminder;

    @Mock
    User user;

    @Mock
    Timer mockTimer;

    @Mock
    TimerTask mockTask;
    
    @BeforeEach
    public void setUp() {
        TimerTask task = new MyTask(user);
        mockTask = mock(task.getClass());

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

            @Override
            public TimerTask createTask() {
                return mockTask;
            }
        };
    }

    @Test
    void testRemind() throws Exception {
        dailyReminder.remind();  // here is the line where NullPointerException occured
        verify(mockTimer).scheduleAtFixedRate(eq(mockTask), any(Date.class), anyLong());
    }
}

DailyReminder.java

public class DailyReminder {

    private Timer timer;
    private TimerTask task;
    private User user;
    private Date dateStart;
    private final Duration fixedDuration = Duration.of(1, ChronoUnit.DAYS);
    
    // some constructor here...
    
    public void remind() {
        timer = createTimer();
        task = createTask();
        timer.scheduleAtFixedRate(task, dateStart, fixedDuration.toMillis());
    }

    public Timer createTimer() {
        return new Timer();
    }

    public TimerTask createTask() {
        return new MyTask(user);
    }
}

我也试过 assertNull(dailyReminder) 但是堆栈跟踪显示

org.opentest4j.AssertionFailedError: expected: <null> but was: <Daily Reminder>

奇怪的是 dailyReminder 不为空。有什么解释吗?

如果您正在使用 PowerMockRunner,则必须调用 MockitoAnnotations.initMocks() 以初始化使用注释创建的模拟。当前 mockTimer 为 null,给您 NPE。您可以像对其他模拟所做的那样在 beforeEach 中初始化它,或者调用 initMocks() 来解决这个问题。