Tests for ErrorResponse hierarchy to verify the output

See gh-27052
This commit is contained in:
rstoyanchev
2022-02-28 11:20:07 +00:00
parent 679432ece6
commit b045e5baef
20 changed files with 400 additions and 42 deletions

View File

@@ -61,7 +61,7 @@ public class ErrorResponseException extends NestedRuntimeException implements Er
* Constructor with a well-known {@link HttpStatus} and an optional cause.
*/
public ErrorResponseException(HttpStatus status, @Nullable Throwable cause) {
this(status.value(), null);
this(status.value(), cause);
}
/**

View File

@@ -17,6 +17,7 @@
package org.springframework.web;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -39,15 +40,17 @@ public class HttpMediaTypeNotAcceptableException extends HttpMediaTypeException
*/
public HttpMediaTypeNotAcceptableException(String message) {
super(message);
getBody().setDetail("Could not parse Accept header");
getBody().setDetail("Could not parse Accept header.");
}
/**
* Create a new HttpMediaTypeNotSupportedException.
* @param supportedMediaTypes the list of supported media types
* @param mediaTypes the list of supported media types
*/
public HttpMediaTypeNotAcceptableException(List<MediaType> supportedMediaTypes) {
super("No acceptable representation", supportedMediaTypes);
public HttpMediaTypeNotAcceptableException(List<MediaType> mediaTypes) {
super("No acceptable representation", mediaTypes);
getBody().setDetail("Acceptable representations: " +
mediaTypes.stream().map(MediaType::toString).collect(Collectors.joining(", ", "'", "'")) + ".");
}

View File

@@ -51,29 +51,29 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
super(message);
this.contentType = null;
this.httpMethod = null;
getBody().setDetail("Could not parse Content-Type");
getBody().setDetail("Could not parse Content-Type.");
}
/**
* Create a new HttpMediaTypeNotSupportedException.
* @param contentType the unsupported content type
* @param supportedMediaTypes the list of supported media types
* @param mediaTypes the list of supported media types
*/
public HttpMediaTypeNotSupportedException(@Nullable MediaType contentType, List<MediaType> supportedMediaTypes) {
this(contentType, supportedMediaTypes, null);
public HttpMediaTypeNotSupportedException(@Nullable MediaType contentType, List<MediaType> mediaTypes) {
this(contentType, mediaTypes, null);
}
/**
* Create a new HttpMediaTypeNotSupportedException.
* @param contentType the unsupported content type
* @param supportedMediaTypes the list of supported media types
* @param mediaTypes the list of supported media types
* @param httpMethod the HTTP method of the request
* @since 6.0
*/
public HttpMediaTypeNotSupportedException(@Nullable MediaType contentType,
List<MediaType> supportedMediaTypes, @Nullable HttpMethod httpMethod) {
public HttpMediaTypeNotSupportedException(
@Nullable MediaType contentType, List<MediaType> mediaTypes, @Nullable HttpMethod httpMethod) {
this(contentType, supportedMediaTypes, httpMethod,
this(contentType, mediaTypes, httpMethod,
"Content-Type " + (contentType != null ? "'" + contentType + "' " : "") + "is not supported");
}
@@ -91,7 +91,7 @@ public class HttpMediaTypeNotSupportedException extends HttpMediaTypeException {
super(message, supportedMediaTypes);
this.contentType = contentType;
this.httpMethod = httpMethod;
getBody().setDetail("Content-Type " + this.contentType + " is not supported");
getBody().setDetail("Content-Type '" + this.contentType + "' is not supported.");
}

View File

@@ -93,8 +93,9 @@ public class HttpRequestMethodNotSupportedException extends ServletException imp
super(msg);
this.method = method;
this.supportedMethods = supportedMethods;
this.body = ProblemDetail.forRawStatusCode(getRawStatusCode())
.withDetail("Method '" + method + "' is not supported");
String detail = "Method '" + method + "' is not supported.";
this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail(detail);
}

View File

@@ -48,7 +48,7 @@ public class MethodArgumentNotValidException extends BindException implements Er
public MethodArgumentNotValidException(MethodParameter parameter, BindingResult bindingResult) {
super(bindingResult);
this.parameter = parameter;
this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail(initMessage(parameter));
this.body = ProblemDetail.forRawStatusCode(getRawStatusCode()).withDetail("Invalid request content.");
}
@@ -71,13 +71,9 @@ public class MethodArgumentNotValidException extends BindException implements Er
@Override
public String getMessage() {
return initMessage(this.parameter);
}
private String initMessage(MethodParameter parameter) {
StringBuilder sb = new StringBuilder("Validation failed for argument [")
.append(parameter.getParameterIndex()).append("] in ")
.append(parameter.getExecutable().toGenericString());
.append(this.parameter.getParameterIndex()).append("] in ")
.append(this.parameter.getExecutable().toGenericString());
BindingResult bindingResult = getBindingResult();
if (bindingResult.getErrorCount() > 1) {
sb.append(" with ").append(bindingResult.getErrorCount()).append(" errors");

View File

@@ -57,7 +57,7 @@ public class MissingMatrixVariableException extends MissingRequestValueException
super("", missingAfterConversion);
this.variableName = variableName;
this.parameter = parameter;
getBody().setDetail("Required path parameter '" + this.variableName + "' is not present");
getBody().setDetail("Required path parameter '" + this.variableName + "' is not present.");
}

View File

@@ -60,7 +60,7 @@ public class MissingPathVariableException extends MissingRequestValueException {
super("", missingAfterConversion);
this.variableName = variableName;
this.parameter = parameter;
getBody().setDetail("Required URI variable '" + this.variableName + "' is not present");
getBody().setDetail("Required path variable '" + this.variableName + "' is not present.");
}

View File

@@ -57,7 +57,7 @@ public class MissingRequestCookieException extends MissingRequestValueException
super("", missingAfterConversion);
this.cookieName = cookieName;
this.parameter = parameter;
getBody().setDetail("Required cookie '" + this.cookieName + "' is not present");
getBody().setDetail("Required cookie '" + this.cookieName + "' is not present.");
}

View File

@@ -57,7 +57,7 @@ public class MissingRequestHeaderException extends MissingRequestValueException
super("", missingAfterConversion);
this.headerName = headerName;
this.parameter = parameter;
getBody().setDetail("Required header '" + this.headerName + "' is not present");
getBody().setDetail("Required header '" + this.headerName + "' is not present.");
}

View File

@@ -52,7 +52,7 @@ public class MissingServletRequestParameterException extends MissingRequestValue
super("", missingAfterConversion);
this.parameterName = parameterName;
this.parameterType = parameterType;
getBody().setDetail("Required parameter '" + this.parameterName + "' is not present");
getBody().setDetail("Required parameter '" + this.parameterName + "' is not present.");
}

View File

@@ -16,7 +16,6 @@
package org.springframework.web.bind;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -48,9 +47,7 @@ public class UnsatisfiedServletRequestParameterException extends ServletRequestB
* @param actualParams the actual parameter Map associated with the ServletRequest
*/
public UnsatisfiedServletRequestParameterException(String[] paramConditions, Map<String, String[]> actualParams) {
super("");
this.paramConditions = Arrays.<String[]>asList(paramConditions);
this.actualParams = actualParams;
this(List.<String[]>of(paramConditions), actualParams);
}
/**
@@ -66,6 +63,7 @@ public class UnsatisfiedServletRequestParameterException extends ServletRequestB
Assert.notEmpty(paramConditions, "Parameter conditions must not be empty");
this.paramConditions = paramConditions;
this.actualParams = actualParams;
getBody().setDetail("Invalid request parameters.");
}

View File

@@ -49,6 +49,7 @@ public class WebExchangeBindException extends ServerWebInputException implements
public WebExchangeBindException(MethodParameter parameter, BindingResult bindingResult) {
super("Validation failure", parameter);
this.bindingResult = bindingResult;
getBody().setDetail("Invalid request content.");
}

View File

@@ -40,7 +40,7 @@ public class MissingServletRequestPartException extends ServletRequestBindingExc
* @param requestPartName the name of the missing part of the multipart request
*/
public MissingServletRequestPartException(String requestPartName) {
super("Required request part '" + requestPartName + "' is not present");
super("Required part '" + requestPartName + "' is not present.");
this.requestPartName = requestPartName;
getBody().setDetail(getMessage());
}

View File

@@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -47,13 +48,17 @@ public class MethodNotAllowedException extends ResponseStatusException {
}
public MethodNotAllowedException(String method, @Nullable Collection<HttpMethod> supportedMethods) {
super(HttpStatus.METHOD_NOT_ALLOWED, "Request method '" + method + "' not supported");
super(HttpStatus.METHOD_NOT_ALLOWED, "Request method '" + method + "' is not supported.");
Assert.notNull(method, "'method' is required");
if (supportedMethods == null) {
supportedMethods = Collections.emptySet();
}
this.method = method;
this.httpMethods = Collections.unmodifiableSet(new LinkedHashSet<>(supportedMethods));
getBody().setDetail(this.httpMethods.isEmpty() ? getReason() :
"Supported methods: " + this.httpMethods.stream()
.map(HttpMethod::toString).collect(Collectors.joining("', '", "'", "'")));
}

View File

@@ -18,6 +18,7 @@ package org.springframework.web.server;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -42,14 +43,17 @@ public class NotAcceptableStatusException extends ResponseStatusException {
public NotAcceptableStatusException(String reason) {
super(HttpStatus.NOT_ACCEPTABLE, reason);
this.supportedMediaTypes = Collections.emptyList();
getBody().setDetail("Could not parse Accept header.");
}
/**
* Constructor for when the requested Content-Type is not supported.
*/
public NotAcceptableStatusException(List<MediaType> supportedMediaTypes) {
public NotAcceptableStatusException(List<MediaType> mediaTypes) {
super(HttpStatus.NOT_ACCEPTABLE, "Could not find acceptable representation");
this.supportedMediaTypes = Collections.unmodifiableList(supportedMediaTypes);
this.supportedMediaTypes = Collections.unmodifiableList(mediaTypes);
getBody().setDetail("Acceptable representations: " +
mediaTypes.stream().map(MediaType::toString).collect(Collectors.joining(", ", "'", "'")) + ".");
}

View File

@@ -77,7 +77,6 @@ public class ResponseStatusException extends ErrorResponseException {
public ResponseStatusException(int rawStatusCode, @Nullable String reason, @Nullable Throwable cause) {
super(rawStatusCode, cause);
this.reason = reason;
setDetail(reason);
}

View File

@@ -57,6 +57,7 @@ public class UnsupportedMediaTypeStatusException extends ResponseStatusException
this.supportedMediaTypes = Collections.emptyList();
this.bodyType = null;
this.method = null;
getBody().setDetail("Could not parse Content-Type.");
}
/**
@@ -100,8 +101,7 @@ public class UnsupportedMediaTypeStatusException extends ResponseStatusException
this.bodyType = bodyType;
this.method = method;
// Set explicitly to avoid implementation details
setDetail(contentType != null ? "Content-Type '" + contentType + "' is not supported" : null);
setDetail(contentType != null ? "Content-Type '" + contentType + "' is not supported." : null);
}