Spring Test with mockMVC throws ServletException

1.1k Views Asked by At

I have the following Spring test class:


@AutoConfigureMockMvc
@Testcontainers
@ExtendWith(SpringExtension.class)
@SpringBootTest
@ActiveProfiles("test")
public class FormTest {

    @Autowired
    private MockMvc mockMvc;
    

    @Test
    public void givenInvalidForm_whenSubmitted_returns400() throws Exception {

        FormUploadDTO dto = .. generate DTO
        MvcResult mvcResult =  mockMvc.perform(post(BaseApi.BASE_API + "/forms")
                        .contentType(MediaType.APPLICATION_JSON.getMediaType())
                        .content(asJsonString(new ArrayList<>(Collections.singleton(dto)){}))
                        .andDo(print())
                        .andReturn();
        assertEquals(400, mvcResult.getResponse().getStatus());


    }

}

however, instead of spring-application container returning bad-request (for @NotNull annotated fields), it throws the following error:

jakarta.servlet.ServletException: Request processing failed: jakarta.validation.ConstraintViolationException: submitForm.dtos[0].client: must not be null, submitForm.dtos[0].priceType: must not be null, submitForm.dtos[0].price: must not be null, submitForm.dtos[0].materialType: must not be null, submitForm.dtos[0].dateTo: must not be null, submitForm.dtos[0].client: must not be blank, submitForm.dtos[0].dateFrom: must not be null

    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1019)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter ....


Caused by: jakarta.validation.ConstraintViolationException: submitForm.dtos[0].client: must not be null, submitForm.dtos[0].priceType: must not be null, submitForm.dtos[0].price: must not be null, submitForm.dtos[0].materialType: must not be null, submitForm.dtos[0].dateTo: must not be null, submitForm.dtos[0].client: must not be blank, submitForm.dtos[0].dateFrom: must not be null
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:138)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)

any idea how this can be fixed?

1

There are 1 best solutions below

0
Ken Chan On

If MockMvc#perform() throws exception , it implies you do not configure spring-mvc to handle this exception.(i.e ConstraintViolationException in your case).

In reality, the exception will be propagated back to the servlet container to let it handle (e.g decide what HTTP response will be returned etc).But now as you are using MockMvc , you can think that it is a mocked version of servlet container which its implementation is just throw the exception for any exception propagated to it.

So the answer is to configure spring-mvc to handle ConstraintViolationException , for example by declaring a @ControllerAdvice for it :

@ControllerAdvice
public class ApiExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public void handleConstraintViolationException(final ConstraintViolationException ex) {
        log.info("handle ConstraintViolationException blabla",ex);
    }
}

Note : See more how to handle exception in spring-mvc at this