Powermock+JUnit - 带有新 class 的 NullPointerException
Powermock+JUnit - NullPointerException with new class
当我尝试模拟一个方法并且该方法有一个带有新 class 的局部变量时出现 NullPointerException。尝试了不同的方式,但没有运气。请查看评论,我已经提到了我的尝试以及出现异常的地方。
提前致谢!
@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;
}
解决方案:
我使用的是 org.hamcrest.CoreMatchers.any
导致编译错误 Type mismatch: cannot convert from Matcher<Student> to Student
现在我改成了org.mockito.ArgumentMatcher.any
您可以选择以下两个之一。两者都会起作用。
密钥正在导入 org.mockito.ArgumentMatcher.any
Student student =mock(Student.class);
student.setName("Name");
student.setAddress("New York");
或
Student student = new Student();
student.setName("Name");
student.setAddress("New York");
基于被测方法、与 new Student() 的紧密耦合以及测试中的匹配器设置与被测方法中创建的匹配器设置不匹配这一事实,那么 studentService.create
将 return null.
确实不需要 Student
模拟,因为被测方法已经在创建一个。
使用更灵活的参数匹配器,如 any(Student.class)
,在设置中捕获传递的参数并设置所需的 ID,以便被测方法可以完成。
例如
@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());
}
}
当我尝试模拟一个方法并且该方法有一个带有新 class 的局部变量时出现 NullPointerException。尝试了不同的方式,但没有运气。请查看评论,我已经提到了我的尝试以及出现异常的地方。
提前致谢!
@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;
}
解决方案:
我使用的是 org.hamcrest.CoreMatchers.any
导致编译错误 Type mismatch: cannot convert from Matcher<Student> to Student
现在我改成了org.mockito.ArgumentMatcher.any
您可以选择以下两个之一。两者都会起作用。
密钥正在导入 org.mockito.ArgumentMatcher.any
Student student =mock(Student.class);
student.setName("Name");
student.setAddress("New York");
或
Student student = new Student();
student.setName("Name");
student.setAddress("New York");
基于被测方法、与 new Student() 的紧密耦合以及测试中的匹配器设置与被测方法中创建的匹配器设置不匹配这一事实,那么 studentService.create
将 return null.
确实不需要 Student
模拟,因为被测方法已经在创建一个。
使用更灵活的参数匹配器,如 any(Student.class)
,在设置中捕获传递的参数并设置所需的 ID,以便被测方法可以完成。
例如
@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());
}
}