/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.web.servlet.mvc.support; import java.lang.reflect.Method; import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.TypeMismatchException; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.tests.sample.beans.TestBean; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.BindException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingPathVariableException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.context.request.async.AsyncRequestTimeoutException; import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.NoHandlerFoundException; import static org.junit.Assert.*; /** * @author Arjen Poutsma */ public class DefaultHandlerExceptionResolverTests { private final DefaultHandlerExceptionResolver exceptionResolver = new DefaultHandlerExceptionResolver(); private final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); private final MockHttpServletResponse response = new MockHttpServletResponse(); @Before public void setup() { exceptionResolver.setWarnLogCategory(exceptionResolver.getClass().getName()); } @Test public void handleHttpRequestMethodNotSupported() { HttpRequestMethodNotSupportedException ex = new HttpRequestMethodNotSupportedException("GET", new String[]{"POST", "PUT"}); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 405, response.getStatus()); assertEquals("Invalid Allow header", "POST, PUT", response.getHeader("Allow")); } @Test public void handleHttpMediaTypeNotSupported() { HttpMediaTypeNotSupportedException ex = new HttpMediaTypeNotSupportedException(new MediaType("text", "plain"), Collections.singletonList(new MediaType("application", "pdf"))); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 415, response.getStatus()); assertEquals("Invalid Accept header", "application/pdf", response.getHeader("Accept")); } @Test public void handleMissingPathVariable() throws NoSuchMethodException { Method method = getClass().getMethod("handle", String.class); MethodParameter parameter = new MethodParameter(method, 0); MissingPathVariableException ex = new MissingPathVariableException("foo", parameter); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 500, response.getStatus()); assertEquals("Missing URI template variable 'foo' for method parameter of type String", response.getErrorMessage()); } @Test public void handleMissingServletRequestParameter() { MissingServletRequestParameterException ex = new MissingServletRequestParameterException("foo", "bar"); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); assertEquals("Required bar parameter 'foo' is not present", response.getErrorMessage()); } @Test public void handleServletRequestBindingException() { String message = "Missing required value - header, cookie, or pathvar"; ServletRequestBindingException ex = new ServletRequestBindingException(message); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); } @Test public void handleTypeMismatch() { TypeMismatchException ex = new TypeMismatchException("foo", String.class); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); } @Test public void handleHttpMessageNotReadable() { HttpMessageNotReadableException ex = new HttpMessageNotReadableException("foo"); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); } @Test public void handleHttpMessageNotWritable() { HttpMessageNotWritableException ex = new HttpMessageNotWritableException("foo"); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 500, response.getStatus()); } @Test public void handleMethodArgumentNotValid() throws Exception { BeanPropertyBindingResult errors = new BeanPropertyBindingResult(new TestBean(), "testBean"); errors.rejectValue("name", "invalid"); MethodParameter parameter = new MethodParameter(this.getClass().getMethod("handle", String.class), 0); MethodArgumentNotValidException ex = new MethodArgumentNotValidException(parameter, errors); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); } @Test public void handleMissingServletRequestPartException() throws Exception { MissingServletRequestPartException ex = new MissingServletRequestPartException("name"); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); assertTrue(response.getErrorMessage().contains("request part")); assertTrue(response.getErrorMessage().contains("name")); assertTrue(response.getErrorMessage().contains("not present")); } @Test public void handleBindException() throws Exception { BindException ex = new BindException(new Object(), "name"); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 400, response.getStatus()); } @Test public void handleNoHandlerFoundException() throws Exception { ServletServerHttpRequest req = new ServletServerHttpRequest( new MockHttpServletRequest("GET","/resource")); NoHandlerFoundException ex = new NoHandlerFoundException(req.getMethod().name(), req.getServletRequest().getRequestURI(),req.getHeaders()); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 404, response.getStatus()); } @Test public void handleConversionNotSupportedException() throws Exception { ConversionNotSupportedException ex = new ConversionNotSupportedException(new Object(), String.class, new Exception()); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 500, response.getStatus()); // SPR-9653 assertSame(ex, request.getAttribute("javax.servlet.error.exception")); } @Test // SPR-14669 public void handleAsyncRequestTimeoutException() throws Exception { Exception ex = new AsyncRequestTimeoutException(); ModelAndView mav = exceptionResolver.resolveException(request, response, null, ex); assertNotNull("No ModelAndView returned", mav); assertTrue("No Empty ModelAndView returned", mav.isEmpty()); assertEquals("Invalid status code", 503, response.getStatus()); } @SuppressWarnings("unused") public void handle(String arg) { } }