使用 Junit 和 Mockito 嵌套异常问题测试 POST Api

Posted

技术标签:

【中文标题】使用 Junit 和 Mockito 嵌套异常问题测试 POST Api【英文标题】:Testing a POST Api using Junit and Mockito-Nested Exception problem 【发布时间】:2020-01-23 03:46:36 【问题描述】:

我正在尝试使用 JUNIT 和 mockito 测试 API,作为初学者,我没有找到关于我所陈述的问题的任何解决方案

我正在尝试测试一个以

的形式包含员工和部门的 api

        "name": "ABC",
        "age": 20,
        "salary": 2500.0,
        "departmentTest": 
            "deptId": 5,
            "deptName": "Developer"
        
    

这应该是发布请求的正文。 这里有 Employee 和 Department 之间的多对一映射。多个员工可以属于一个部门,映射是双向的。

我收到以下异常:-

**org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
Caused by: java.lang.NullPointerException
    at com.example.controller.EmployeeTestController.addEmployee(EmployeeTestController.java:45)**

特此附上控制器、服务和测试文件:-

控制器文件:-

@Controller
public class EmployeeTestController 

    @Autowired
    private EmployeeTestService employeeTestService;

    @GetMapping("/employee")
    public ResponseEntity<?> getAllEmployee()
    
        return new ResponseEntity<>(employeeTestService.getAllEmployee(),HttpStatus.OK);
    

    @PostMapping("/employee")
    public ResponseEntity<?> addEmployee(@Valid @RequestBody EmployeeTestDTO employeeTestDTO) throws EmployeeException
    
        if(employeeTestDTO.getSalary() <= 0 )
            throw new EmployeeException("Salary Should be greater than Zero");
        
        else 
            employeeTestService.addEmployee(employeeTestDTO);
            return new ResponseEntity<>(HttpStatus.CREATED);
        
    


服务文件:-

@Service
public class EmployeeTestService 

    @Autowired
    private EmployeeTestRespository employeeTestRespository;

    @Autowired
    private DepartmentTestService departmentTestService;

    @Autowired
    private ModelMapper modelMapper;

    public List<EmployeeTestDTO> getAllEmployee()
    
        List<EmployeeTestDTO> empDTO = new ArrayList<EmployeeTestDTO>();
        List<EmployeeTest> emp=employeeTestRespository.findAll();
        for(EmployeeTest e : emp)
        
            empDTO.add(modelMapper.map(e, EmployeeTestDTO.class));
        

        return empDTO;
    

    public Object getIndividualEmployee(Integer id) throws  EmployeeException 
        Optional<EmployeeTest> op_employeeTest = employeeTestRespository.findById(id);
        if(op_employeeTest.isPresent())
        
            return modelMapper.map(op_employeeTest.get(), EmployeeTestDTO.class);

        
        else
        
            throw new EmployeeException("No such employee exist");
        
    

    public void addEmployee(EmployeeTestDTO employeeTestDTO) throws EmployeeException 
         String dept_name = modelMapper.map(employeeTestDTO, EmployeeTest.class).getDepartmentTest().getDeptName();
         DepartmentTest departmentTest = departmentTestService.findDepartmentByDeptName(dept_name);
         if(departmentTest == null)
             throw new EmployeeException("Department doesn't exist");
         
         else 
             EmployeeTest employeeTest = modelMapper.map(employeeTestDTO,EmployeeTest.class);
             employeeTest.setDepartmentTest(departmentTest);
             employeeTestRespository.save(employeeTest);
         
    

测试文件:-

   @RunWith(SpringRunner.class)
   @WebMvcTest(controllers = EmployeeTestController.class)
   @ContextConfiguration(classes = IntegrationTestingForEmployeeApplication.class)
   public class ControllerTesting 

        private MockMvc mockMvc;

        @MockBean
        private EmployeeTestService employeeTestService;

        @InjectMocks
        private EmployeeTestController employeeTestController;

        @MockBean
        private ModelMapper modelMapper;


        DepartmentTest departmentTest ;
        EmployeeTest employeeTest;

        @Before
        public void setUp()throws Exception
        
            System.out.println("Inside Set Up Method");
            mockMvc = MockMvcBuilders.standaloneSetup(employeeTestController)
                        .build();
            departmentTest = new DepartmentTest();
            departmentTest.setDeptId(1);
            departmentTest.setDeptName("Sales");

        

        @Test
        public void controllerTesting() throws Exception
        
            System.out.println(departmentTest.getDeptId());
            System.out.println(departmentTest.getDeptName());

               String json =  "\"name\":\"ABC\",\"age\":20,\"salary\":2500,\"departmentTest\":\"deptId\":5,\"deptName\":\"Developer\"";
               mockMvc.perform(post("/employee")
                       .contentType(MediaType.APPLICATION_JSON)
                       .content(json))
                       .andExpect(status().isCreated())
                       .andExpect(jsonPath("$.name", Matchers.is("ABC")))
                       .andExpect(jsonPath("$.age", Matchers.is(20)))
                       .andExpect(jsonPath("$.salary", Matchers.is(2500)));


           


    

【问题讨论】:

【参考方案1】:

你得到了employeeTestService 的空指针。

这意味着employeeTestService 没有从您的测试文件中注入。

我认为你错过了 setup() 方法中的 initMocks

@Before
public void setUp()throws Exception


    MockitoAnnotations.initMocks(this);

    System.out.println("Inside Set Up Method");
    mockMvc = MockMvcBuilders.standaloneSetup(employeeTestController)
                .build();
    departmentTest = new DepartmentTest();
    departmentTest.setDeptId(1);
    departmentTest.setDeptName("Sales");

【讨论】:

以上是关于使用 Junit 和 Mockito 嵌套异常问题测试 POST Api的主要内容,如果未能解决你的问题,请参考以下文章

Mockito 如何模拟和断言抛出的异常?

Junit mockito 测试Controller层方法有Pageable异常

如何在 JUnit5 中使用 Mockito

如何使用 mockito 和 junit 测试此功能?

如何使用 Mockito 和 JUnit 在 Spring Boot 中测试 POST 方法

使用 JUnit 和 Mockito 对 DAO 类进行单元测试