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