Search code examples
spring-bootcontrollermockmvcspringrunner

How To Handle Exception in Test Case


@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
@ContextConfiguration(classes = Application.class)
public class MyControllerTest {

@Autowired
MockMvc mockMvc;
@MockBean
EmployeeService employeeService;
@MockBean
EmployeeRepo employeeRepo;
@MockBean
ValidationService validationService;

@Before
public  void setup(){
     emp=new Employee();
     objectMapper=new ObjectMapper();
     emp.setId("123");
     emp.setAge(100);
     emp.setName("pasam");

    System.out.println("Employee object before Test"+emp);
}
@Test
public void createEmp() throws Exception{
    mockMvc.perform(MockMvcRequestBuilders.post("/sample/insert")
        .accept(MediaType.APPLICATION_JSON_VALUE)
        .contentType(MediaType.APPLICATION_JSON_VALUE)
        .content(objectMapper.writeValueAsString(emp))).andExpect(status().isOk()).andDo(print());


}

}

@RestController
@RequestMapping("/sample")
public class MyController {

@Autowired
private EmployeeService employeeService;
@Autowired
private ValidationService validationService;

 @PostMapping(value = "/insert",consumes = MediaType.APPLICATION_JSON_VALUE)
public  ResponseEntity insertEmployee(@RequestBody Employee employee){
    validationService.validateEmp(employee);
    employeeService.create(employee);
    return ResponseEntity.ok().build();

}

}

public interface ValidationService {
  void validateEmp(Employee employee) ;
}

@Slf4j
@Service
public class ValidateServiceImpl implements ValidationService {

@Override
public void validateEmp(Employee employee) {
    if(employee.getAge()!=0){
       log.info("Age can not be 0");
    }
}

}

I am trying to write Test Cases for Spring boot controller by using Spring Runner ,In my controller i want to validate employee object,for that i have written Validate Service interface .Above Test case Passed with validate employee.while debugging above test case.debug point not going into validationServiceImpl class.I want to throw error while Validate Employee Object.How to handle exception in test case.


Solution

  • Actually you mock the ValidationService dependency :

    @MockBean
    ValidationService validationService;
    

    And you specify no mock behavior for. So it allows to make the validatorService dependency to be invoked without throwing any exception. It works as the validateEmp() method is not designed to return anything required for the workflow of the method under test.

    As reminder, a test annotated with WebMvcTest is designed to focus on the controller testing, not the service testing.
    You could remove the @MockBean annotation to make validationService the real implementation and not a mock :

    ValidationService validationService;
    

    But note that a better way to test unitary the ValidationService is creating a unit test for it.

    At last note also that a still better way would be to use the javax.validation API to valid the input.
    You could annotation in the Employee class to define the constraints on the fields and in the controller to validate the parameter such as :

    import javax.validation.Valid;
     ...
    @PostMapping(value = "/insert",consumes = MediaType.APPLICATION_JSON_VALUE)
    public  ResponseEntity insertEmployee(@Valid @RequestBody Employee employe){
     //  validationService.validateEmp(employee); // Not required any longer
         employeeService.create(employee);
         return ResponseEntity.ok().build();    
     }