Search code examples
javaunit-testingmockitojunit4powermockito

NullPointerException when powermockito testing method invocation


I'm new to unit testing with powermockito and currently i'm trying to test a method that calls java.util.Timer.scheduleAtFixedRate. I've tried to run the test but it failed and showed NullPointerException at the line where an object invoke a method that i suppose my object here is not null. Here is my code, i've summarized the part that may cause the problem.

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);
    }
}

I also have tried assertNull(dailyReminder) however the stack trace shows

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

which is weird that dailyReminder there wasn't null. Is there any explanation for this?


Solution

  • If you are using the PowerMockRunner, you have to call MockitoAnnotations.initMocks() in order to initialise the mocks that are created using the annotations. Currently mockTimer is null giving you NPE. You can either initialise it in beforeEach like you are doing for other mocks or call initMocks() to fix this.