I'm writing unit test for controller, this time I purposely made a request which will trigger ConstrainViolationException, in mockmvc instead of expect it throws the error. How can I tell spring not to throw it and let mvcresult verify the result
Here is my code snippet
@WebMvcTest(ProductController.class)
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ProductService productService;
@BeforeEach
public void setUp() throws Exception
{
this.mockMvc = MockMvcBuilders.standaloneSetup(new ProductController(productService))
.setControllerAdvice(new ExceptionAdvice())
.build();
}
@Test
public void createProduct_With_InvalidRequest_ShouldReturn_BadRequest() throws Exception {
ProductWebRequest productWebRequest = ProductWebRequest.builder()
.sku(null)
.productName(null)
.barcode(null)
.build();
ProductServiceWebRequest productServiceWebRequest = ProductServiceWebRequest.builder()
.sku(productWebRequest.getSku())
.productName(productWebRequest.getProductName())
.barcode(productWebRequest.getBarcode())
.build();
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(productWebRequest);
BDDMockito.given(productService.createProduct(productServiceWebRequest)).willThrow(ConstraintViolationException.class);
mockMvc.perform(MockMvcRequestBuilders.post("/v1/products")
.contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(MockMvcResultMatchers.status().isBadRequest())
.andExpect(mvcResult -> Assertions.assertTrue(mvcResult.getResolvedException() instanceof ConstraintViolationException));
}
}
ProductController.java
@RestController
@RequestMapping("/v1")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@PostMapping(value = "/products", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public WebResponse createProduct(@RequestBody ProductWebRequest request)
{
ProductServiceWebRequest productServiceWebRequest = ProductServiceWebRequest.builder()
.sku(request.getSku())
.productName(request.getProductName())
.barcode(request.getBarcode())
.description(request.getDescription())
.brand(request.getBrand())
.material(request.getMaterial())
.motif(request.getMotif())
.colour(request.getColour())
.price(request.getPrice())
.weight(request.getWeight())
.length(request.getLength())
.width(request.getWidth())
.height(request.getHeight())
.category(request.getCategory())
.hasVariant(request.getHasVariant())
.build();
ProductCreatedWebResponse productCreatedWebResponse = productService.createProduct(productServiceWebRequest);
return WebResponse.builder()
.statusCode(HttpStatus.OK.value())
.statusName(HttpStatus.OK.name())
.data(productCreatedWebResponse)
.build();
}
ExceptionAdvice.java
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice
@Slf4j
public class ExceptionAdvice extends ResponseEntityExceptionHandler {
@Override
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
{
List<String> errors = new ArrayList<>();
for (FieldError error : ex.getBindingResult().getFieldErrors())
{
errors.add(error.getField() + " : " + error.getDefaultMessage());
}
for (ObjectError error : ex.getBindingResult().getGlobalErrors())
{
errors.add(error.getObjectName() +" : "+ error.getDefaultMessage());
}
WebResponse webResponse = WebResponse.builder()
.error("API_ERROR")
.errorDetail("REQUEST_NOT_CONFORM_PAYLOAD_STANDARD")
.statusCode(HttpStatus.BAD_REQUEST.value())
.statusName(HttpStatus.BAD_REQUEST.name())
.build();
log.error(errors.toString());
return handleExceptionInternal(ex, webResponse, headers, HttpStatus.BAD_REQUEST, request);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler({ConstraintViolationException.class})
public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request)
{
List<String> errors = new ArrayList<String>();
for (ConstraintViolation<?> violation : ex.getConstraintViolations())
{
errors.add(violation.getRootBeanClass().getSimpleName() + " - " + violation.getPropertyPath() + " : " + violation.getMessage().toUpperCase());
}
WebResponse webResponse = WebResponse.builder()
.error("API_FAIL")
.errorDetail("REQUEST_NOT_CONFORM_PAYLOAD_STANDARD")
.statusCode(HttpStatus.BAD_REQUEST.value())
.statusName(HttpStatus.BAD_REQUEST.name())
.build();
log.error(errors.toString());
return new ResponseEntity<Object>(webResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST);
}
}
And this is the error that appears
(ProductControllerTest.java:50)
Caused by: javax.validation.ConstraintViolationException
I know this will throw an exception, but how can I use that exception in the expect section for assertions?