SK.
SK.

Reputation: 1510

Powermock+JUnit - NullPointerException with new class

Getting NullPointerException when I try to mock a method and that method has a local variable with new class. Tried different way, but no luck. Please see the comments, I have mentioned what I tried and where I am getting exception.

Thanks in advance!

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(StudentController.class)
    public class StudentControllerTest {
        @Mock
        HttpServletRequest request;

        @Mock
        StudentService studentService;

        @InjectMocks
        StudentController studentController;
        @Test
        public void create() {
            Student student =mock(Student.class);
            **// Also tried Student student = new Student();**
            student.setName("Name");
            student.setAddress("New York");

            when(studentService.create(student)).thenReturn(student);
            // if I try below code I am getting compile error - Type mismatch: cannot convert from Matcher<Student> to Student
 //when(studentService.create(any(Student.class))).thenReturn(student);
            Student createdStudent= studentController("Name", "New York", 1);
            assertTrue(0 < createdStudent.getStudentId())
        }
    }

Studentcontroller.java

@PostMapping("/api/student/create")
public Student create(HttpServletRequest request, @RequestParam("name") String name, @RequestParam("address") String address, @RequestParam("grade") String grade) {

    Student student = new Student();
    try {
        student.setName(name);
        student.setAddress(address);
        student.setGrade(Integer.decode(grade));

        student = studentService.create(student);
        **// Throwing NullPointer in this line. I did dubug and can see student returned is null**
        message = "Successfully Created Student[" + student.getId() + "] " + name;  

    } catch (Exception e) {
        message = "Exception while create the student: " + name;
        log.error(message + "\n" + StackTraceUtil.getStackTrace(e));
        student.setErrorMessage(message);
    }

    return student;
}

SOLUTION:

I was using org.hamcrest.CoreMatchers.any That gives compile error Type mismatch: cannot convert from Matcher<Student> to Student

Now I changed it to org.mockito.ArgumentMatcher.any You can either one of below two. Both will work.

The key was importing org.mockito.ArgumentMatcher.any

Student student =mock(Student.class);
student.setName("Name");
student.setAddress("New York");

OR

Student student = new Student();
student.setName("Name");
student.setAddress("New York");

Upvotes: 1

Views: 660

Answers (1)

Nkosi
Nkosi

Reputation: 247363

Based on the method under test, the tight coupling to new Student() and the fact that the matcher setup in the test wont match the one created in the method under test, then studentService.create will return null.

There really is no need for a Student mock since the method under test is already creating one.

Use a more flexible argument matcher like any(Student.class), capture the passed argument in the setup and set the desired id so the method under test can flow to completion.

For example

@RunWith(PowerMockRunner.class)
@PrepareForTest(StudentController.class)
public class StudentControllerTest {
    @Mock
    HttpServletRequest request;

    @Mock
    StudentService studentService;

    @InjectMocks
    StudentController studentController;

    @Test
    public void create() {
        //Arrange
        int expectedId = 1;
        when(studentService.create(any(Student.class)))
            .thenAnswer(i -> {
                Student student = (Student)i.getArguments()[0];
                //manipulate the student as needed.
                //Like setting an id

                //...student.setId(expectedId)

                return student;
            });

        //Act
        Student createdStudent = studentController.create(request, "Name", "New York", 1);

        //Assert
        assertTrue(createdStudent != null);
        assertTrue(expectedId == createdStudent.getStudentId());
    }
}

Upvotes: 2

Related Questions