Reputation: 1510
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
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