Consistent use of @Nullable in spring-test

This commit also removes nullability from two common spots: ResolvableType.getType() and TargetSource.getTarget(), both of which are never effectively null with any regular implementation. For such scenarios, a non-null empty type/target is the cleaner contract.

Issue: SPR-15540
This commit is contained in:
Juergen Hoeller
2017-06-08 22:52:57 +02:00
parent ee5fa2633a
commit fd53d2a51a
134 changed files with 812 additions and 777 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -72,10 +72,7 @@ public class MockClientHttpResponse extends MockHttpInputMessage implements Clie
@Override
public void close() {
try {
InputStream body = getBody();
if (body != null) {
body.close();
}
getBody().close();
}
catch (IOException ex) {
// ignore

View File

@@ -72,7 +72,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
super(uri, headers);
this.httpMethod = httpMethod;
this.contextPath = (contextPath != null ? contextPath : "");
this.contextPath = contextPath;
this.cookies = cookies;
this.remoteAddress = remoteAddress;
this.body = Flux.from(body);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -33,6 +33,7 @@ import javax.naming.OperationNotSupportedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
@@ -80,7 +81,9 @@ public class SimpleNamingContext implements Context {
* Create a new naming context with the given naming root,
* the given name/object map, and the JNDI environment entries.
*/
public SimpleNamingContext(String root, Hashtable<String, Object> boundObjects, Hashtable<String, Object> env) {
public SimpleNamingContext(
String root, Hashtable<String, Object> boundObjects, @Nullable Hashtable<String, Object> env) {
this.root = root;
this.boundObjects = boundObjects;
if (env != null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -17,7 +17,6 @@
package org.springframework.mock.jndi;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
@@ -195,7 +194,7 @@ public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder
* @see SimpleNamingContext
*/
@Override
public InitialContextFactory createInitialContextFactory(Hashtable<?,?> environment) {
public InitialContextFactory createInitialContextFactory(@Nullable Hashtable<?,?> environment) {
if (activated == null && environment != null) {
Object icf = environment.get(Context.INITIAL_CONTEXT_FACTORY);
if (icf != null) {

View File

@@ -68,10 +68,12 @@ class HeaderValueHolder {
return Collections.unmodifiableList(stringList);
}
@Nullable
public Object getValue() {
return (!this.values.isEmpty() ? this.values.get(0) : null);
}
@Nullable
public String getStringValue() {
return (!this.values.isEmpty() ? String.valueOf(this.values.get(0)) : null);
}

View File

@@ -55,7 +55,7 @@ public class MockAsyncContext implements AsyncContext {
private final List<Runnable> dispatchHandlers = new ArrayList<>();
public MockAsyncContext(ServletRequest request, ServletResponse response) {
public MockAsyncContext(ServletRequest request, @Nullable ServletResponse response) {
this.request = (HttpServletRequest) request;
this.response = (HttpServletResponse) response;
}

View File

@@ -24,6 +24,8 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import org.springframework.lang.Nullable;
/**
* Mock implementation of the {@link javax.servlet.jsp.tagext.BodyContent} class.
* Only necessary for testing applications when testing custom JSP tags.
@@ -60,12 +62,12 @@ public class MockBodyContent extends BodyContent {
* @param response the servlet response to wrap
* @param targetWriter the target Writer to wrap
*/
public MockBodyContent(String content, HttpServletResponse response, Writer targetWriter) {
public MockBodyContent(String content, @Nullable HttpServletResponse response, @Nullable Writer targetWriter) {
super(adaptJspWriter(targetWriter, response));
this.content = content;
}
private static JspWriter adaptJspWriter(Writer targetWriter, HttpServletResponse response) {
private static JspWriter adaptJspWriter(@Nullable Writer targetWriter, @Nullable HttpServletResponse response) {
if (targetWriter instanceof JspWriter) {
return (JspWriter) targetWriter;
}

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -64,7 +65,7 @@ public class MockFilterConfig implements FilterConfig {
* Create a new MockFilterConfig.
* @param servletContext the ServletContext that the servlet runs in
*/
public MockFilterConfig(ServletContext servletContext) {
public MockFilterConfig(@Nullable ServletContext servletContext) {
this(servletContext, "");
}
@@ -73,7 +74,7 @@ public class MockFilterConfig implements FilterConfig {
* @param servletContext the ServletContext that the servlet runs in
* @param filterName the name of the filter
*/
public MockFilterConfig(ServletContext servletContext, String filterName) {
public MockFilterConfig(@Nullable ServletContext servletContext, String filterName) {
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
this.filterName = filterName;
}

View File

@@ -41,7 +41,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
@@ -64,6 +63,7 @@ import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
@@ -370,6 +370,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public String getCharacterEncoding() {
return this.characterEncoding;
}
@@ -449,7 +450,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
return getContentLength();
}
public void setContentType(String contentType) {
public void setContentType(@Nullable String contentType) {
this.contentType = contentType;
if (contentType != null) {
try {
@@ -470,6 +471,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public String getContentType() {
return this.contentType;
}
@@ -530,7 +532,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
* <p>If there are already one or more values registered for the given
* parameter name, the given value will be added to the end of the list.
*/
public void addParameter(String name, String value) {
public void addParameter(String name, @Nullable String value) {
addParameter(name, new String[] {value});
}
@@ -591,8 +593,10 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public String getParameter(String name) {
String[] arr = (name != null ? this.parameters.get(name) : null);
Assert.notNull(name, "Parameter name must not be null");
String[] arr = this.parameters.get(name);
return (arr != null && arr.length > 0 ? arr[0] : null);
}
@@ -603,7 +607,8 @@ public class MockHttpServletRequest implements HttpServletRequest {
@Override
public String[] getParameterValues(String name) {
return (name != null ? this.parameters.get(name) : null);
Assert.notNull(name, "Parameter name must not be null");
return this.parameters.get(name);
}
@Override
@@ -709,7 +714,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
public void setAttribute(String name, Object value) {
public void setAttribute(String name, @Nullable Object value) {
checkActive();
Assert.notNull(name, "Attribute name must not be null");
if (value != null) {
@@ -903,6 +908,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public AsyncContext getAsyncContext() {
return this.asyncContext;
}
@@ -930,17 +936,18 @@ public class MockHttpServletRequest implements HttpServletRequest {
return this.authType;
}
public void setCookies(Cookie... cookies) {
this.cookies = cookies;
public void setCookies(@Nullable Cookie... cookies) {
this.cookies = (ObjectUtils.isEmpty(cookies) ? null : cookies);
this.headers.remove(HttpHeaders.COOKIE);
if (cookies != null) {
Arrays.stream(cookies)
if (this.cookies != null) {
Arrays.stream(this.cookies)
.map(c -> c.getName() + '=' + (c.getValue() == null ? "" : c.getValue()))
.forEach(value -> doAddHeaderValue(HttpHeaders.COOKIE, value, false));
}
}
@Override
@Nullable
public Cookie[] getCookies() {
return this.cookies;
}
@@ -978,7 +985,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
}
private void doAddHeaderValue(String name, Object value, boolean replace) {
private void doAddHeaderValue(String name, @Nullable Object value, boolean replace) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
Assert.notNull(value, "Header value must not be null");
if (header == null || replace) {
@@ -1045,6 +1052,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public String getHeader(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getStringValue() : null);
@@ -1098,6 +1106,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public String getPathTranslated() {
return (this.pathInfo != null ? getRealPath(this.pathInfo) : null);
}
@@ -1111,7 +1120,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
return this.contextPath;
}
public void setQueryString(String queryString) {
public void setQueryString(@Nullable String queryString) {
this.queryString = queryString;
}
@@ -1120,7 +1129,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
return this.queryString;
}
public void setRemoteUser(String remoteUser) {
public void setRemoteUser(@Nullable String remoteUser) {
this.remoteUser = remoteUser;
}
@@ -1197,6 +1206,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public HttpSession getSession(boolean create) {
checkActive();
// Reset session if invalidated.
@@ -1211,6 +1221,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public HttpSession getSession() {
return getSession(true);
}
@@ -1284,6 +1295,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
@Override
@Nullable
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
return this.parts.getFirst(name);
}

View File

@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@@ -171,6 +170,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
}
@Override
@Nullable
public String getCharacterEncoding() {
return this.characterEncoding;
}
@@ -224,7 +224,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
}
@Override
public void setContentType(String contentType) {
public void setContentType(@Nullable String contentType) {
this.contentType = contentType;
if (contentType != null) {
try {
@@ -247,6 +247,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
}
@Override
@Nullable
public String getContentType() {
return this.contentType;
}
@@ -302,7 +303,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
}
@Override
public void setLocale(Locale locale) {
public void setLocale(@Nullable Locale locale) {
this.locale = locale;
if (locale != null) {
doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, locale.toLanguageTag(), true);
@@ -357,6 +358,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
return this.cookies.toArray(new Cookie[this.cookies.size()]);
}
@Nullable
public Cookie getCookie(String name) {
Assert.notNull(name, "Cookie name must not be null");
for (Cookie cookie : this.cookies) {
@@ -502,6 +504,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
setCommitted(true);
}
@Nullable
public String getRedirectedUrl() {
return getHeader(HttpHeaders.LOCATION);
}
@@ -639,17 +642,19 @@ public class MockHttpServletResponse implements HttpServletResponse {
this.forwardedUrl = forwardedUrl;
}
@Nullable
public String getForwardedUrl() {
return this.forwardedUrl;
}
public void setIncludedUrl(String includedUrl) {
public void setIncludedUrl(@Nullable String includedUrl) {
this.includedUrls.clear();
if (includedUrl != null) {
this.includedUrls.add(includedUrl);
}
}
@Nullable
public String getIncludedUrl() {
int count = this.includedUrls.size();
Assert.state(count <= 1,

View File

@@ -29,6 +29,7 @@ import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -79,7 +80,7 @@ public class MockHttpSession implements HttpSession {
* Create a new MockHttpSession.
* @param servletContext the ServletContext that the session runs in
*/
public MockHttpSession(ServletContext servletContext) {
public MockHttpSession(@Nullable ServletContext servletContext) {
this(servletContext, null);
}
@@ -88,7 +89,7 @@ public class MockHttpSession implements HttpSession {
* @param servletContext the ServletContext that the session runs in
* @param id a unique identifier for this session
*/
public MockHttpSession(ServletContext servletContext, String id) {
public MockHttpSession(@Nullable ServletContext servletContext, @Nullable String id) {
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
this.id = (id != null ? id : Integer.toString(nextId++));
}
@@ -171,7 +172,7 @@ public class MockHttpSession implements HttpSession {
}
@Override
public void setAttribute(String name, Object value) {
public void setAttribute(String name, @Nullable Object value) {
assertIsValid();
Assert.notNull(name, "Attribute name must not be null");
if (value != null) {

View File

@@ -22,6 +22,8 @@ import java.io.Writer;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
import org.springframework.lang.Nullable;
/**
* Mock implementation of the {@link javax.servlet.jsp.JspWriter} class.
* Only necessary for testing applications when testing custom JSP tags.
@@ -58,7 +60,7 @@ public class MockJspWriter extends JspWriter {
* @param response the servlet response to wrap
* @param targetWriter the target Writer to wrap
*/
public MockJspWriter(HttpServletResponse response, Writer targetWriter) {
public MockJspWriter(@Nullable HttpServletResponse response, @Nullable Writer targetWriter) {
super(DEFAULT_BUFFER, true);
this.response = (response != null ? response : new MockHttpServletResponse());
if (targetWriter instanceof PrintWriter) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@@ -21,6 +21,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
@@ -53,7 +54,7 @@ public class MockMultipartFile implements MultipartFile {
* @param name the name of the file
* @param content the content of the file
*/
public MockMultipartFile(String name, byte[] content) {
public MockMultipartFile(String name, @Nullable byte[] content) {
this(name, "", null, content);
}
@@ -74,7 +75,9 @@ public class MockMultipartFile implements MultipartFile {
* @param contentType the content type (if known)
* @param content the content of the file
*/
public MockMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
public MockMultipartFile(
String name, @Nullable String originalFilename, @Nullable String contentType, @Nullable byte[] content) {
Assert.hasLength(name, "Name must not be null");
this.name = name;
this.originalFilename = (originalFilename != null ? originalFilename : "");
@@ -90,7 +93,8 @@ public class MockMultipartFile implements MultipartFile {
* @param contentStream the content of the file as stream
* @throws IOException if reading from the stream failed
*/
public MockMultipartFile(String name, String originalFilename, String contentType, InputStream contentStream)
public MockMultipartFile(
String name, @Nullable String originalFilename, @Nullable String contentType, InputStream contentStream)
throws IOException {
this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));

View File

@@ -36,6 +36,7 @@ import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -79,7 +80,7 @@ public class MockPageContext extends PageContext {
* @param servletContext the ServletContext that the JSP page runs in
* (only necessary when actually accessing the ServletContext)
*/
public MockPageContext(ServletContext servletContext) {
public MockPageContext(@Nullable ServletContext servletContext) {
this(servletContext, null, null, null);
}
@@ -90,7 +91,7 @@ public class MockPageContext extends PageContext {
* @param request the current HttpServletRequest
* (only necessary when actually accessing the request)
*/
public MockPageContext(ServletContext servletContext, HttpServletRequest request) {
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request) {
this(servletContext, request, null, null);
}
@@ -101,7 +102,9 @@ public class MockPageContext extends PageContext {
* @param response the current HttpServletResponse
* (only necessary when actually writing to the response)
*/
public MockPageContext(ServletContext servletContext, HttpServletRequest request, HttpServletResponse response) {
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request,
@Nullable HttpServletResponse response) {
this(servletContext, request, response, null);
}
@@ -112,8 +115,8 @@ public class MockPageContext extends PageContext {
* @param response the current HttpServletResponse
* @param servletConfig the ServletConfig (hardly ever accessed from within a tag)
*/
public MockPageContext(ServletContext servletContext, HttpServletRequest request,
HttpServletResponse response, ServletConfig servletConfig) {
public MockPageContext(@Nullable ServletContext servletContext, @Nullable HttpServletRequest request,
@Nullable HttpServletResponse response, @Nullable ServletConfig servletConfig) {
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
this.request = (request != null ? request : new MockHttpServletRequest(servletContext));
@@ -135,7 +138,7 @@ public class MockPageContext extends PageContext {
}
@Override
public void setAttribute(String name, Object value) {
public void setAttribute(String name, @Nullable Object value) {
Assert.notNull(name, "Attribute name must not be null");
if (value != null) {
this.attributes.put(name, value);
@@ -146,7 +149,7 @@ public class MockPageContext extends PageContext {
}
@Override
public void setAttribute(String name, Object value, int scope) {
public void setAttribute(String name, @Nullable Object value, int scope) {
Assert.notNull(name, "Attribute name must not be null");
switch (scope) {
case PAGE_SCOPE:
@@ -167,12 +170,14 @@ public class MockPageContext extends PageContext {
}
@Override
@Nullable
public Object getAttribute(String name) {
Assert.notNull(name, "Attribute name must not be null");
return this.attributes.get(name);
}
@Override
@Nullable
public Object getAttribute(String name, int scope) {
Assert.notNull(name, "Attribute name must not be null");
switch (scope) {
@@ -191,6 +196,7 @@ public class MockPageContext extends PageContext {
}
@Override
@Nullable
public Object findAttribute(String name) {
Object value = getAttribute(name);
if (value == null) {
@@ -267,7 +273,7 @@ public class MockPageContext extends PageContext {
return this.request.getAttributeNames();
case SESSION_SCOPE:
HttpSession session = this.request.getSession(false);
return (session != null ? session.getAttributeNames() : null);
return (session != null ? session.getAttributeNames() : Collections.emptyEnumeration());
case APPLICATION_SCOPE:
return this.servletContext.getAttributeNames();
default:
@@ -290,12 +296,14 @@ public class MockPageContext extends PageContext {
}
@Override
@Nullable
public ELContext getELContext() {
return null;
}
@Override
@Deprecated
@Nullable
public javax.servlet.jsp.el.VariableResolver getVariableResolver() {
return null;
}
@@ -321,6 +329,7 @@ public class MockPageContext extends PageContext {
}
@Override
@Nullable
public Exception getException() {
return null;
}

View File

@@ -20,14 +20,15 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import javax.servlet.http.Part;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
/**
* Mock implementation of {@code javax.servlet.http.Part}.
*
@@ -55,7 +56,7 @@ public class MockPart implements Part {
/**
* Constructor for a part with a filename.
*/
public MockPart(String name, String filename, InputStream content) throws IOException {
public MockPart(String name, @Nullable String filename, InputStream content) throws IOException {
this(name, filename, FileCopyUtils.copyToByteArray(content));
}
@@ -63,7 +64,7 @@ public class MockPart implements Part {
* Constructor for a part with byte[] content only.
* @see #getHeaders()
*/
private MockPart(String name, String filename, byte[] content) {
private MockPart(String name, @Nullable String filename, @Nullable byte[] content) {
Assert.hasLength(name, "Name must not be null");
this.name = name;
this.filename = filename;
@@ -83,6 +84,7 @@ public class MockPart implements Part {
}
@Override
@Nullable
public String getContentType() {
MediaType contentType = this.headers.getContentType();
return (contentType != null ? contentType.toString() : null);
@@ -99,13 +101,15 @@ public class MockPart implements Part {
}
@Override
@Nullable
public String getHeader(String name) {
return this.headers.getFirst(name);
}
@Override
public Collection<String> getHeaders(String name) {
return this.headers.get(name);
Collection<String> headerValues = this.headers.get(name);
return (headerValues != null ? headerValues : Collections.emptyList());
}
@Override

View File

@@ -23,6 +23,7 @@ import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -60,7 +61,7 @@ public class MockServletConfig implements ServletConfig {
* Create a new MockServletConfig.
* @param servletContext the ServletContext that the servlet runs in
*/
public MockServletConfig(ServletContext servletContext) {
public MockServletConfig(@Nullable ServletContext servletContext) {
this(servletContext, "");
}
@@ -69,7 +70,7 @@ public class MockServletConfig implements ServletConfig {
* @param servletContext the ServletContext that the servlet runs in
* @param servletName the name of the servlet
*/
public MockServletConfig(ServletContext servletContext, String servletName) {
public MockServletConfig(@Nullable ServletContext servletContext, String servletName) {
this.servletContext = (servletContext != null ? servletContext : new MockServletContext());
this.servletName = servletName;
}

View File

@@ -182,7 +182,7 @@ public class MockServletContext implements ServletContext {
*/
public MockServletContext(String resourceBasePath, @Nullable ResourceLoader resourceLoader) {
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
this.resourceBasePath = (resourceBasePath != null ? resourceBasePath : "");
this.resourceBasePath = resourceBasePath;
// Use JVM temp dir as ServletContext temp dir.
String tempDir = System.getProperty(TEMP_DIR_SYSTEM_PROPERTY);
@@ -207,7 +207,7 @@ public class MockServletContext implements ServletContext {
}
public void setContextPath(String contextPath) {
this.contextPath = (contextPath != null ? contextPath : "");
this.contextPath = contextPath;
}
@Override
@@ -287,6 +287,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public Set<String> getResourcePaths(String path) {
String actualPath = (path.endsWith("/") ? path : path + "/");
Resource resource = this.resourceLoader.getResource(getResourceLocation(actualPath));
@@ -313,6 +314,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public URL getResource(String path) throws MalformedURLException {
Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
if (!resource.exists()) {
@@ -331,6 +333,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public InputStream getResourceAsStream(String path) {
Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
if (!resource.exists()) {
@@ -410,6 +413,7 @@ public class MockServletContext implements ServletContext {
@Override
@Deprecated
@Nullable
public Servlet getServlet(String name) {
return null;
}
@@ -443,6 +447,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public String getRealPath(String path) {
Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
try {
@@ -486,6 +491,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public Object getAttribute(String name) {
Assert.notNull(name, "Attribute name must not be null");
return this.attributes.get(name);
@@ -497,7 +503,7 @@ public class MockServletContext implements ServletContext {
}
@Override
public void setAttribute(String name, Object value) {
public void setAttribute(String name, @Nullable Object value) {
Assert.notNull(name, "Attribute name must not be null");
if (value != null) {
this.attributes.put(name, value);
@@ -523,6 +529,7 @@ public class MockServletContext implements ServletContext {
}
@Override
@Nullable
public ClassLoader getClassLoader() {
return ClassUtils.getDefaultClassLoader();
}

View File

@@ -47,6 +47,7 @@ import org.springframework.web.server.WebSession;
/**
* Mock implementation of {@link ServerRequest}.
*
* @author Arjen Poutsma
* @since 5.0
*/
@@ -70,9 +71,9 @@ public class MockServerRequest implements ServerRequest {
private Principal principal;
private MockServerRequest(HttpMethod method, URI uri,
MockHeaders headers, @Nullable Object body, Map<String, Object> attributes,
MultiValueMap<String, String> queryParams,
private MockServerRequest(HttpMethod method, URI uri, MockHeaders headers, @Nullable Object body,
Map<String, Object> attributes, MultiValueMap<String, String> queryParams,
Map<String, String> pathVariables, WebSession session, Principal principal) {
this.method = method;
@@ -104,25 +105,29 @@ public class MockServerRequest implements ServerRequest {
@Override
@SuppressWarnings("unchecked")
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor){
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor) {
Assert.state(this.body != null, "No body");
return (S) this.body;
}
@Override
@SuppressWarnings("unchecked")
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor, Map<String, Object> hints) {
Assert.state(this.body != null, "No body");
return (S) this.body;
}
@Override
@SuppressWarnings("unchecked")
public <S> Mono<S> bodyToMono(Class<? extends S> elementClass) {
Assert.state(this.body != null, "No body");
return (Mono<S>) this.body;
}
@Override
@SuppressWarnings("unchecked")
public <S> Flux<S> bodyToFlux(Class<? extends S> elementClass) {
Assert.state(this.body != null, "No body");
return (Flux<S>) this.body;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -77,6 +77,7 @@ public abstract class ProfileValueUtils {
}
else {
profileValueSourceType = (Class<? extends ProfileValueSource>) AnnotationUtils.getDefaultValue(annotationType);
Assert.state(profileValueSourceType != null, "No default ProfileValueSource class");
}
if (logger.isDebugEnabled()) {
logger.debug("Retrieved ProfileValueSource type [" + profileValueSourceType + "] for class [" +

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -158,7 +158,7 @@ public @interface ContextConfiguration {
* @see #inheritInitializers
* @see #loader
*/
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
Class<? extends ApplicationContextInitializer<?>>[] initializers() default {};
/**
* Whether or not {@link #locations resource locations} or <em>annotated

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -58,7 +58,7 @@ public class ContextConfigurationAttributes {
private final boolean inheritLocations;
private final Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers;
private final Class<? extends ApplicationContextInitializer<?>>[] initializers;
private final boolean inheritInitializers;
@@ -101,9 +101,10 @@ public class ContextConfigurationAttributes {
*/
@SuppressWarnings("unchecked")
public ContextConfigurationAttributes(Class<?> declaringClass, AnnotationAttributes annAttrs) {
this(declaringClass, annAttrs.getStringArray("locations"), annAttrs.getClassArray("classes"), annAttrs.getBoolean("inheritLocations"),
(Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[]) annAttrs.getClassArray("initializers"),
annAttrs.getBoolean("inheritInitializers"), annAttrs.getString("name"), (Class<? extends ContextLoader>) annAttrs.getClass("loader"));
this(declaringClass, annAttrs.getStringArray("locations"), annAttrs.getClassArray("classes"),
annAttrs.getBoolean("inheritLocations"),
(Class<? extends ApplicationContextInitializer<?>>[]) annAttrs.getClassArray("initializers"),
annAttrs.getBoolean("inheritInitializers"), annAttrs.getString("name"), annAttrs.getClass("loader"));
}
/**
@@ -123,7 +124,7 @@ public class ContextConfigurationAttributes {
*/
public ContextConfigurationAttributes(
Class<?> declaringClass, String[] locations, Class<?>[] classes, boolean inheritLocations,
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers,
Class<? extends ApplicationContextInitializer<?>>[] initializers,
boolean inheritInitializers, Class<? extends ContextLoader> contextLoaderClass) {
this(declaringClass, locations, classes, inheritLocations, initializers, inheritInitializers, null,
@@ -148,11 +149,11 @@ public class ContextConfigurationAttributes {
*/
public ContextConfigurationAttributes(
Class<?> declaringClass, String[] locations, Class<?>[] classes, boolean inheritLocations,
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers,
boolean inheritInitializers, String name, Class<? extends ContextLoader> contextLoaderClass) {
Class<? extends ApplicationContextInitializer<?>>[] initializers,
boolean inheritInitializers, @Nullable String name, Class<? extends ContextLoader> contextLoaderClass) {
Assert.notNull(declaringClass, "declaringClass must not be null");
Assert.notNull(contextLoaderClass, "contextLoaderClass must not be null");
Assert.notNull(declaringClass, "'declaringClass' must not be null");
Assert.notNull(contextLoaderClass, "'contextLoaderClass' must not be null");
if (!ObjectUtils.isEmpty(locations) && !ObjectUtils.isEmpty(classes) && logger.isDebugEnabled()) {
logger.debug(String.format(
@@ -199,13 +200,12 @@ public class ContextConfigurationAttributes {
* <p>Note: this is a mutable property. The returned value may therefore
* represent a <em>processed</em> value that does not match the original value
* declared via {@link ContextConfiguration @ContextConfiguration}.
* @return the annotated classes; potentially {@code null} or <em>empty</em>
* @return the annotated classes (potentially {<em>empty</em>)
* @see ContextConfiguration#classes
* @see #setClasses(Class[])
*/
@Nullable
public Class<?>[] getClasses() {
return this.classes;
return (this.classes != null ? this.classes : new Class<?>[0]);
}
/**
@@ -234,14 +234,13 @@ public class ContextConfigurationAttributes {
* <p>Note: this is a mutable property. The returned value may therefore
* represent a <em>processed</em> value that does not match the original value
* declared via {@link ContextConfiguration @ContextConfiguration}.
* @return the resource locations; potentially {@code null} or <em>empty</em>
* @return the resource locations (potentially <em>empty</em>)
* @see ContextConfiguration#value
* @see ContextConfiguration#locations
* @see #setLocations(String[])
* @see #setLocations
*/
@Nullable
public String[] getLocations() {
return this.locations;
return (this.locations != null ? this.locations : new String[0]);
}
/**
@@ -283,7 +282,7 @@ public class ContextConfigurationAttributes {
* @return the {@code ApplicationContextInitializer} classes
* @since 3.2
*/
public Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] getInitializers() {
public Class<? extends ApplicationContextInitializer<?>>[] getInitializers() {
return this.initializers;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -60,7 +60,7 @@ public interface ContextLoader {
* application context (can be {@code null} or empty)
* @return an array of application context resource locations
*/
String[] processLocations(Class<?> clazz, @Nullable String... locations);
String[] processLocations(Class<?> clazz, String... locations);
/**
* Loads a new {@link ApplicationContext context} based on the supplied

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -24,7 +24,6 @@ import java.util.Set;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.style.ToStringCreator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -73,8 +72,8 @@ public class MergedContextConfiguration implements Serializable {
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
private static final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> EMPTY_INITIALIZER_CLASSES =
Collections.<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> emptySet();
private static final Set<Class<? extends ApplicationContextInitializer<?>>> EMPTY_INITIALIZER_CLASSES =
Collections.<Class<? extends ApplicationContextInitializer<?>>> emptySet();
private static final Set<ContextCustomizer> EMPTY_CONTEXT_CUSTOMIZERS = Collections.<ContextCustomizer> emptySet();
@@ -85,7 +84,7 @@ public class MergedContextConfiguration implements Serializable {
private final Class<?>[] classes;
private final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses;
private final Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses;
private final String[] activeProfiles;
@@ -102,52 +101,9 @@ public class MergedContextConfiguration implements Serializable {
private final MergedContextConfiguration parent;
private static String[] processStrings(String[] array) {
return (array != null ? array : EMPTY_STRING_ARRAY);
}
private static Class<?>[] processClasses(Class<?>[] classes) {
return (classes != null ? classes : EMPTY_CLASS_ARRAY);
}
private static Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> processContextInitializerClasses(
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses) {
return (contextInitializerClasses != null ?
Collections.unmodifiableSet(contextInitializerClasses) : EMPTY_INITIALIZER_CLASSES);
}
private static Set<ContextCustomizer> processContextCustomizers(Set<ContextCustomizer> contextCustomizers) {
return (contextCustomizers != null ?
Collections.unmodifiableSet(contextCustomizers) : EMPTY_CONTEXT_CUSTOMIZERS);
}
private static String[] processActiveProfiles(String[] activeProfiles) {
if (activeProfiles == null) {
return EMPTY_STRING_ARRAY;
}
// Active profiles must be unique
Set<String> profilesSet = new LinkedHashSet<>(Arrays.asList(activeProfiles));
return StringUtils.toStringArray(profilesSet);
}
/**
* Generate a null-safe {@link String} representation of the supplied
* {@link ContextLoader} based solely on the fully qualified name of the
* loader or &quot;null&quot; if the supplied loader is {@code null}.
*/
@Nullable
protected static String nullSafeToString(@Nullable ContextLoader contextLoader) {
return (contextLoader != null ? contextLoader.getClass().getName() : "null");
}
/**
* Create a new {@code MergedContextConfiguration} instance for the
* supplied parameters.
* <p>Delegates to
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
* @param testClass the test class for which the configuration was merged
* @param locations the merged context resource locations
* @param classes the merged annotated classes
@@ -163,18 +119,15 @@ public class MergedContextConfiguration implements Serializable {
/**
* Create a new {@code MergedContextConfiguration} instance for the
* supplied parameters.
* <p>Delegates to
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
* @param testClass the test class for which the configuration was merged
* @param locations the merged context resource locations
* @param classes the merged annotated classes
* @param contextInitializerClasses the merged context initializer classes
* @param activeProfiles the merged active bean definition profiles
* @param contextLoader the resolved {@code ContextLoader}
* @see #MergedContextConfiguration(Class, String[], Class[], Set, String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)
*/
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
String[] activeProfiles, ContextLoader contextLoader) {
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, contextLoader, null, null);
@@ -183,8 +136,6 @@ public class MergedContextConfiguration implements Serializable {
/**
* Create a new {@code MergedContextConfiguration} instance for the
* supplied parameters.
* <p>Delegates to
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
* @param testClass the test class for which the configuration was merged
* @param locations the merged context resource locations
* @param classes the merged annotated classes
@@ -197,12 +148,13 @@ public class MergedContextConfiguration implements Serializable {
* @since 3.2.2
*/
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
String[] activeProfiles, ContextLoader contextLoader,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
@Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
@Nullable MergedContextConfiguration parent) {
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, null, null, contextLoader,
cacheAwareContextLoaderDelegate, parent);
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, null, null,
contextLoader, cacheAwareContextLoaderDelegate, parent);
}
/**
@@ -212,9 +164,9 @@ public class MergedContextConfiguration implements Serializable {
*/
public MergedContextConfiguration(MergedContextConfiguration mergedConfig) {
this(mergedConfig.testClass, mergedConfig.locations, mergedConfig.classes,
mergedConfig.contextInitializerClasses, mergedConfig.activeProfiles, mergedConfig.propertySourceLocations,
mergedConfig.propertySourceProperties, mergedConfig.contextCustomizers,
mergedConfig.contextLoader, mergedConfig.cacheAwareContextLoaderDelegate, mergedConfig.parent);
mergedConfig.contextInitializerClasses, mergedConfig.activeProfiles, mergedConfig.propertySourceLocations,
mergedConfig.propertySourceProperties, mergedConfig.contextCustomizers,
mergedConfig.contextLoader, mergedConfig.cacheAwareContextLoaderDelegate, mergedConfig.parent);
}
/**
@@ -241,10 +193,12 @@ public class MergedContextConfiguration implements Serializable {
* @since 4.1
*/
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
@Nullable Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
@Nullable String[] propertySourceProperties, ContextLoader contextLoader,
@Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
@Nullable MergedContextConfiguration parent) {
this(testClass, locations, classes, contextInitializerClasses, activeProfiles,
propertySourceLocations, propertySourceProperties,
EMPTY_CONTEXT_CUSTOMIZERS, contextLoader,
@@ -276,10 +230,11 @@ public class MergedContextConfiguration implements Serializable {
* @since 4.3
*/
public MergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
@Nullable Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
@Nullable Set<ContextCustomizer> contextCustomizers, ContextLoader contextLoader,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations,
@Nullable String[] propertySourceProperties, @Nullable Set<ContextCustomizer> contextCustomizers,
ContextLoader contextLoader, @Nullable CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
@Nullable MergedContextConfiguration parent) {
this.testClass = testClass;
this.locations = processStrings(locations);
@@ -361,7 +316,7 @@ public class MergedContextConfiguration implements Serializable {
* Get the merged {@code ApplicationContextInitializer} classes for the
* {@linkplain #getTestClass() test class}.
*/
public Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> getContextInitializerClasses() {
public Set<Class<? extends ApplicationContextInitializer<?>>> getContextInitializerClasses() {
return this.contextInitializerClasses;
}
@@ -455,7 +410,7 @@ public class MergedContextConfiguration implements Serializable {
* {@link #getContextLoader() ContextLoaders}.
*/
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
@@ -495,7 +450,7 @@ public class MergedContextConfiguration implements Serializable {
return false;
}
if (!nullSafeToString(this.contextLoader).equals(nullSafeToString(otherConfig.contextLoader))) {
if (!nullSafeClassName(this.contextLoader).equals(nullSafeClassName(otherConfig.contextLoader))) {
return false;
}
@@ -517,7 +472,7 @@ public class MergedContextConfiguration implements Serializable {
result = 31 * result + Arrays.hashCode(this.propertySourceProperties);
result = 31 * result + this.contextCustomizers.hashCode();
result = 31 * result + (this.parent != null ? this.parent.hashCode() : 0);
result = 31 * result + nullSafeToString(this.contextLoader).hashCode();
result = 31 * result + nullSafeClassName(this.contextLoader).hashCode();
return result;
}
@@ -543,9 +498,51 @@ public class MergedContextConfiguration implements Serializable {
.append("propertySourceLocations", ObjectUtils.nullSafeToString(this.propertySourceLocations))
.append("propertySourceProperties", ObjectUtils.nullSafeToString(this.propertySourceProperties))
.append("contextCustomizers", this.contextCustomizers)
.append("contextLoader", nullSafeToString(this.contextLoader))
.append("contextLoader", nullSafeClassName(this.contextLoader))
.append("parent", this.parent)
.toString();
}
private static String[] processStrings(@Nullable String[] array) {
return (array != null ? array : EMPTY_STRING_ARRAY);
}
private static Class<?>[] processClasses(@Nullable Class<?>[] classes) {
return (classes != null ? classes : EMPTY_CLASS_ARRAY);
}
private static Set<Class<? extends ApplicationContextInitializer<?>>> processContextInitializerClasses(
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses) {
return (contextInitializerClasses != null ?
Collections.unmodifiableSet(contextInitializerClasses) : EMPTY_INITIALIZER_CLASSES);
}
private static Set<ContextCustomizer> processContextCustomizers(
@Nullable Set<ContextCustomizer> contextCustomizers) {
return (contextCustomizers != null ?
Collections.unmodifiableSet(contextCustomizers) : EMPTY_CONTEXT_CUSTOMIZERS);
}
private static String[] processActiveProfiles(@Nullable String[] activeProfiles) {
if (activeProfiles == null) {
return EMPTY_STRING_ARRAY;
}
// Active profiles must be unique
Set<String> profilesSet = new LinkedHashSet<>(Arrays.asList(activeProfiles));
return StringUtils.toStringArray(profilesSet);
}
/**
* Generate a null-safe {@link String} representation of the supplied
* {@link ContextLoader} based solely on the fully qualified name of the
* loader or &quot;null&quot; if the supplied loader is {@code null}.
*/
protected static String nullSafeClassName(@Nullable ContextLoader contextLoader) {
return (contextLoader != null ? contextLoader.getClass().getName() : "null");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -65,24 +65,21 @@ public interface TestContext extends AttributeAccessor, Serializable {
* @return the current test instance (may be {@code null})
* @see #updateState(Object, Method, Throwable)
*/
@Nullable
Object getTestInstance();
/**
* Get the current {@linkplain Method test method} for this test context.
* <p>Note: this is a mutable property.
* @return the current test method (may be {@code null})
* @return the current test method
* @see #updateState(Object, Method, Throwable)
*/
@Nullable
Method getTestMethod();
/**
* Get the {@linkplain Throwable exception} that was thrown during execution
* of the {@linkplain #getTestMethod() test method}.
* <p>Note: this is a mutable property.
* @return the exception that was thrown, or {@code null} if no
* exception was thrown
* @return the exception that was thrown, or {@code null} if no exception was thrown
* @see #updateState(Object, Method, Throwable)
*/
@Nullable
@@ -101,14 +98,13 @@ public interface TestContext extends AttributeAccessor, Serializable {
void markApplicationContextDirty(@Nullable HierarchyMode hierarchyMode);
/**
* Update this test context to reflect the state of the currently executing
* test.
* Update this test context to reflect the state of the currently executing test.
* <p>Caution: concurrent invocations of this method might not be thread-safe,
* depending on the underlying implementation.
* @param testInstance the current test instance (may be {@code null})
* @param testMethod the current test method (may be {@code null})
* @param testException the exception that was thrown in the test method, or
* {@code null} if no exception was thrown
* @param testException the exception that was thrown in the test method,
* or {@code null} if no exception was thrown
*/
void updateState(@Nullable Object testInstance, @Nullable Method testMethod, @Nullable Throwable testException);

View File

@@ -233,7 +233,6 @@ public class TestContextManager {
* @see #getTestExecutionListeners()
*/
public void prepareTestInstance(Object testInstance) throws Exception {
Assert.notNull(testInstance, "Test instance must not be null");
if (logger.isTraceEnabled()) {
logger.trace("prepareTestInstance(): instance [" + testInstance + "]");
}
@@ -501,7 +500,6 @@ public class TestContextManager {
}
private void prepareForBeforeCallback(String callbackName, Object testInstance, Method testMethod) {
Assert.notNull(testInstance, "Test instance must not be null");
if (logger.isTraceEnabled()) {
logger.trace(String.format("%s(): instance [%s], method [%s]", callbackName, testInstance, testMethod));
}
@@ -509,8 +507,8 @@ public class TestContextManager {
}
private void prepareForAfterCallback(String callbackName, Object testInstance, Method testMethod,
Throwable exception) {
Assert.notNull(testInstance, "Test instance must not be null");
@Nullable Throwable exception) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("%s(): instance [%s], method [%s], exception [%s]", callbackName, testInstance,
testMethod, exception));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -160,12 +160,14 @@ public class DefaultContextCache implements ContextCache {
public void remove(MergedContextConfiguration key, @Nullable HierarchyMode hierarchyMode) {
Assert.notNull(key, "Key must not be null");
// startKey is the level at which to begin clearing the cache, depending
// on the configured hierarchy mode.
// startKey is the level at which to begin clearing the cache,
// depending on the configured hierarchy mode.s
MergedContextConfiguration startKey = key;
if (hierarchyMode == HierarchyMode.EXHAUSTIVE) {
while (startKey.getParent() != null) {
startKey = startKey.getParent();
MergedContextConfiguration parent = startKey.getParent();
while (parent != null) {
startKey = parent;
parent = startKey.getParent();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -23,7 +23,6 @@ import java.util.function.Function;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ContainerExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
@@ -142,7 +141,8 @@ abstract class AbstractExpressionEvaluatingCondition implements ContainerExecuti
if (loadContext) {
applicationContext = SpringExtension.getApplicationContext(extensionContext);
} else {
}
else {
gac = new GenericApplicationContext();
gac.refresh();
applicationContext = gac;
@@ -150,7 +150,7 @@ abstract class AbstractExpressionEvaluatingCondition implements ContainerExecuti
if (!(applicationContext instanceof ConfigurableApplicationContext)) {
if (logger.isWarnEnabled()) {
String contextType = (applicationContext != null ? applicationContext.getClass().getName() : "null");
String contextType = applicationContext.getClass().getName();
logger.warn(String.format("@%s(\"%s\") could not be evaluated on [%s] since the test " +
"ApplicationContext [%s] is not a ConfigurableApplicationContext",
annotationType.getSimpleName(), expression, element, contextType));
@@ -160,17 +160,18 @@ abstract class AbstractExpressionEvaluatingCondition implements ContainerExecuti
ConfigurableBeanFactory configurableBeanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
BeanExpressionResolver expressionResolver = configurableBeanFactory.getBeanExpressionResolver();
Assert.state(expressionResolver != null, "No BeanExpressionResolver");
BeanExpressionContext beanExpressionContext = new BeanExpressionContext(configurableBeanFactory, null);
Object result = expressionResolver.evaluate(configurableBeanFactory.resolveEmbeddedValue(expression),
beanExpressionContext);
Object result = expressionResolver.evaluate(
configurableBeanFactory.resolveEmbeddedValue(expression), beanExpressionContext);
if (gac != null) {
gac.close();
}
if (result instanceof Boolean) {
return ((Boolean) result).booleanValue();
return (Boolean) result;
}
else if (result instanceof String) {
String str = ((String) result).trim().toLowerCase();

View File

@@ -39,6 +39,7 @@ import org.junit.jupiter.api.extension.TestInstancePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestContextManager;
import org.springframework.util.Assert;
@@ -168,6 +169,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
* @see ParameterAutowireUtils#resolveDependency
*/
@Override
@Nullable
public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext) {
Parameter parameter = parameterContext.getParameter();
Class<?> testClass = extensionContext.getTestClass().get();

View File

@@ -73,7 +73,7 @@ public @interface SpringJUnitConfig {
* Alias for {@link ContextConfiguration#initializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
Class<? extends ApplicationContextInitializer<?>>[] initializers() default {};
/**
* Alias for {@link ContextConfiguration#inheritLocations}.

View File

@@ -78,7 +78,7 @@ public @interface SpringJUnitWebConfig {
* Alias for {@link ContextConfiguration#initializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
Class<? extends ApplicationContextInitializer<?>>[] initializers() default {};
/**
* Alias for {@link ContextConfiguration#inheritLocations}.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -31,6 +31,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
/**
* Abstract {@linkplain Transactional transactional} extension of
@@ -201,8 +202,10 @@ public abstract class AbstractTransactionalJUnit4SpringContextTests extends Abst
* @see #setSqlScriptEncoding
*/
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
DataSource ds = this.jdbcTemplate.getDataSource();
Assert.state(ds != null, "No DataSource set");
Resource resource = this.applicationContext.getResource(sqlResourcePath);
new ResourceDatabasePopulator(continueOnError, false, this.sqlScriptEncoding, resource).execute(jdbcTemplate.getDataSource());
new ResourceDatabasePopulator(continueOnError, false, this.sqlScriptEncoding, resource).execute(ds);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -22,7 +22,6 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.internal.runners.model.ReflectiveCallable;
@@ -107,7 +106,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
withRulesMethod = ReflectionUtils.findMethod(SpringJUnit4ClassRunner.class, "withRules",
FrameworkMethod.class, Object.class, Statement.class);
Assert.state(withRulesMethod != null, "SpringJUnit4ClassRunner requires JUnit 4.12 or higher.");
Assert.state(withRulesMethod != null, "SpringJUnit4ClassRunner requires JUnit 4.12 or higher");
ReflectionUtils.makeAccessible(withRulesMethod);
}
@@ -310,7 +309,9 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
* Invoke JUnit's private {@code withRules()} method using reflection.
*/
private Statement withRulesReflectively(FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
return (Statement) ReflectionUtils.invokeMethod(withRulesMethod, this, frameworkMethod, testInstance, statement);
Object result = ReflectionUtils.invokeMethod(withRulesMethod, this, frameworkMethod, testInstance, statement);
Assert.state(result instanceof Statement, "withRules mismatch");
return (Statement) result;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -23,7 +23,6 @@ import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.ClassRule;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
@@ -233,7 +232,9 @@ public class SpringMethodRule implements MethodRule {
"SpringClassRule field [%s] must be annotated with JUnit's @ClassRule annotation. " +
"Consult the javadoc for SpringClassRule for details.", ruleField));
return (SpringClassRule) ReflectionUtils.getField(ruleField, null);
Object result = ReflectionUtils.getField(ruleField, null);
Assert.state(result instanceof SpringClassRule, "SpringClassRule field mismatch");
return (SpringClassRule) result;
}
private static Optional<Field> findSpringClassRuleField(Class<?> testClass) {

View File

@@ -91,7 +91,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
* @see #processLocations(Class, String...)
*/
@Override
public void processContextConfiguration(@Nullable ContextConfigurationAttributes configAttributes) {
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) {
String[] processedLocations =
processLocations(configAttributes.getDeclaringClass(), configAttributes.getLocations());
configAttributes.setLocations(processedLocations);
@@ -143,7 +143,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
private void invokeApplicationContextInitializers(ConfigurableApplicationContext context,
MergedContextConfiguration mergedConfig) {
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses =
Set<Class<? extends ApplicationContextInitializer<?>>> initializerClasses =
mergedConfig.getContextInitializerClasses();
if (initializerClasses.isEmpty()) {
// no ApplicationContextInitializers have been declared -> nothing to do
@@ -153,7 +153,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
List<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances = new ArrayList<>();
Class<?> contextClass = context.getClass();
for (Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>> initializerClass : initializerClasses) {
for (Class<? extends ApplicationContextInitializer<?>> initializerClass : initializerClasses) {
Class<?> initializerContextClass =
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
if (initializerContextClass != null && !initializerContextClass.isInstance(context)) {
@@ -213,7 +213,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
* @see #processContextConfiguration(ContextConfigurationAttributes)
*/
@Override
public final String[] processLocations(Class<?> clazz, @Nullable String... locations) {
public final String[] processLocations(Class<?> clazz, String... locations) {
return (ObjectUtils.isEmpty(locations) && isGenerateDefaultLocations()) ?
generateDefaultLocations(clazz) : modifyLocations(clazz, locations);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -300,6 +300,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
}
// Return the last level in the context hierarchy
Assert.state(mergedConfig != null, "No merged context configuration");
return mergedConfig;
}
else {
@@ -462,7 +463,6 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
Class<? extends ContextLoader> contextLoaderClass = resolveExplicitContextLoaderClass(configAttributesList);
if (contextLoaderClass == null) {
contextLoaderClass = getDefaultContextLoaderClass(testClass);
Assert.state(contextLoaderClass != null, "getDefaultContextLoaderClass() must not return null");
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("Using ContextLoader class [%s] for test class [%s]",

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -31,6 +31,7 @@ import org.springframework.test.context.ActiveProfilesResolver;
import org.springframework.test.util.MetaAnnotationUtils;
import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -107,16 +108,10 @@ abstract class ActiveProfilesUtils {
}
String[] profiles = resolver.resolve(rootDeclaringClass);
if (profiles == null) {
String msg = String.format(
"ActiveProfilesResolver [%s] returned a null array of bean definition profiles",
resolverClass.getName());
logger.error(msg);
throw new IllegalStateException(msg);
if (!ObjectUtils.isEmpty(profiles)) {
profileArrays.add(profiles);
}
profileArrays.add(profiles);
descriptor = (annotation.inheritProfiles() ? MetaAnnotationUtils.findAnnotationDescriptor(
rootDeclaringClass.getSuperclass(), annotationType) : null);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.
@@ -22,7 +22,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.util.ObjectUtils;
@@ -79,7 +78,7 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
* @see #detectDefaultConfigurationClasses(Class)
*/
@Override
public void processContextConfiguration(@Nullable ContextConfigurationAttributes configAttributes) {
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) {
if (!configAttributes.hasClasses() && isGenerateDefaultLocations()) {
configAttributes.setClasses(detectDefaultConfigurationClasses(configAttributes.getDeclaringClass()));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.test.context.SmartContextLoader;
import org.springframework.util.Assert;
@@ -101,7 +102,7 @@ public abstract class AnnotationConfigContextLoaderUtils {
* @param clazz the class to check
* @return {@code true} if the supplied class meets the candidate criteria
*/
private static boolean isDefaultConfigurationClassCandidate(Class<?> clazz) {
private static boolean isDefaultConfigurationClassCandidate(@Nullable Class<?> clazz) {
return (clazz != null && isStaticNonPrivateAndNonFinal(clazz) &&
AnnotatedElementUtils.hasAnnotation(clazz, Configuration.class));
}

View File

@@ -69,11 +69,11 @@ abstract class ApplicationContextInitializerUtils {
* superclasses if appropriate (never {@code null})
* @since 3.2
*/
static Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> resolveInitializerClasses(
static Set<Class<? extends ApplicationContextInitializer<?>>> resolveInitializerClasses(
List<ContextConfigurationAttributes> configAttributesList) {
Assert.notEmpty(configAttributesList, "ContextConfigurationAttributes list must not be empty");
final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = //
final Set<Class<? extends ApplicationContextInitializer<?>>> initializerClasses = //
new HashSet<>();
for (ContextConfigurationAttributes configAttributes : configAttributesList) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -130,9 +130,11 @@ abstract class ContextLoaderUtils {
}
else if (contextHierarchyDeclaredLocally) {
ContextHierarchy contextHierarchy = getAnnotation(declaringClass, contextHierarchyType);
for (ContextConfiguration contextConfiguration : contextHierarchy.value()) {
convertContextConfigToConfigAttributesAndAddToList(
contextConfiguration, rootDeclaringClass, configAttributesList);
if (contextHierarchy != null) {
for (ContextConfiguration contextConfiguration : contextHierarchy.value()) {
convertContextConfigToConfigAttributesAndAddToList(
contextConfiguration, rootDeclaringClass, configAttributesList);
}
}
}
else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -74,15 +74,16 @@ public class DefaultTestContext implements TestContext {
/**
* Construct a new {@code DefaultTestContext} from the supplied arguments.
* @param testClass the test class for this test context; never {@code null}
* @param testClass the test class for this test context
* @param mergedContextConfiguration the merged application context
* configuration for this test context; never {@code null}
* configuration for this test context
* @param cacheAwareContextLoaderDelegate the delegate to use for loading
* and closing the application context for this test context; never {@code null}
* and closing the application context for this test context
*/
public DefaultTestContext(Class<?> testClass, MergedContextConfiguration mergedContextConfiguration,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate) {
Assert.notNull(testClass, "testClass must not be null");
Assert.notNull(testClass, "Test Class must not be null");
Assert.notNull(mergedContextConfiguration, "MergedContextConfiguration must not be null");
Assert.notNull(cacheAwareContextLoaderDelegate, "CacheAwareContextLoaderDelegate must not be null");
this.testClass = testClass;
@@ -132,10 +133,12 @@ public class DefaultTestContext implements TestContext {
}
public final Object getTestInstance() {
Assert.state(this.testInstance != null, "No test instance");
return this.testInstance;
}
public final Method getTestMethod() {
Assert.state(this.testMethod != null, "No test method");
return this.testMethod;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -73,12 +73,11 @@ class TestPropertySourceAttributes {
private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations, boolean inheritLocations,
String[] properties, boolean inheritProperties) {
Assert.notNull(declaringClass, "declaringClass must not be null");
Assert.notNull(declaringClass, "declaringClass must not be null");
if (ObjectUtils.isEmpty(locations) && ObjectUtils.isEmpty(properties)) {
locations = new String[] { detectDefaultPropertiesFile(declaringClass) };
}
this.declaringClass = declaringClass;
this.locations = locations;
this.inheritLocations = inheritLocations;
@@ -86,44 +85,38 @@ class TestPropertySourceAttributes {
this.inheritProperties = inheritProperties;
}
/**
* Get the {@linkplain Class class} that declared {@code @TestPropertySource}.
*
* @return the declaring class; never {@code null}
*/
Class<?> getDeclaringClass() {
return declaringClass;
return this.declaringClass;
}
/**
* Get the resource locations that were declared via {@code @TestPropertySource}.
*
* <p>Note: The returned value may represent a <em>detected default</em>
* that does not match the original value declared via {@code @TestPropertySource}.
*
* @return the resource locations; potentially {@code null} or <em>empty</em>
* @return the resource locations; potentially <em>empty</em>
* @see TestPropertySource#value
* @see TestPropertySource#locations
* @see #setLocations(String[])
*/
@Nullable
String[] getLocations() {
return locations;
return this.locations;
}
/**
* Get the {@code inheritLocations} flag that was declared via {@code @TestPropertySource}.
*
* @return the {@code inheritLocations} flag
* @see TestPropertySource#inheritLocations
*/
boolean isInheritLocations() {
return inheritLocations;
return this.inheritLocations;
}
/**
* Get the inlined properties that were declared via {@code @TestPropertySource}.
*
* @return the inlined properties; potentially {@code null} or <em>empty</em>
* @see TestPropertySource#properties
*/
@@ -134,7 +127,6 @@ class TestPropertySourceAttributes {
/**
* Get the {@code inheritProperties} flag that was declared via {@code @TestPropertySource}.
*
* @return the {@code inheritProperties} flag
* @see TestPropertySource#inheritProperties
*/
@@ -157,6 +149,7 @@ class TestPropertySourceAttributes {
.toString();
}
/**
* Detect a default properties file for the supplied class, as specified
* in the class-level Javadoc for {@link TestPropertySource}.
@@ -174,10 +167,10 @@ class TestPropertySourceAttributes {
return prefixedResourcePath;
}
else {
String msg = String.format("Could not detect default properties file for test [%s]: "
+ "%s does not exist. Either declare the 'locations' or 'properties' attributes "
+ "of @TestPropertySource or make the default properties file available.", testClass.getName(),
classPathResource);
String msg = String.format("Could not detect default properties file for test [%s]: " +
"%s does not exist. Either declare the 'locations' or 'properties' attributes " +
"of @TestPropertySource or make the default properties file available.", testClass.getName(),
classPathResource);
logger.error(msg);
throw new IllegalStateException(msg);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -132,7 +132,10 @@ public abstract class TestPropertySourceUtils {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Processing inlined properties for TestPropertySource attributes %s", attrs));
}
properties.addAll(0, Arrays.asList(attrs.getProperties()));
String[] attrProps = attrs.getProperties();
if (attrProps != null) {
properties.addAll(0, Arrays.asList(attrProps));
}
if (!attrs.isInheritProperties()) {
break;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -30,6 +30,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
/**
* Abstract {@linkplain Transactional transactional} extension of
@@ -185,8 +186,10 @@ public abstract class AbstractTransactionalTestNGSpringContextTests extends Abst
* @see #setSqlScriptEncoding
*/
protected void executeSqlScript(String sqlResourcePath, boolean continueOnError) throws DataAccessException {
DataSource ds = this.jdbcTemplate.getDataSource();
Assert.state(ds != null, "No DataSource set");
Resource resource = this.applicationContext.getResource(sqlResourcePath);
new ResourceDatabasePopulator(continueOnError, false, this.sqlScriptEncoding, resource).execute(jdbcTemplate.getDataSource());
new ResourceDatabasePopulator(continueOnError, false, this.sqlScriptEncoding, resource).execute(ds);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -19,6 +19,7 @@ package org.springframework.test.context.transaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
@@ -56,6 +57,7 @@ class TransactionContext {
TransactionContext(TestContext testContext, PlatformTransactionManager transactionManager,
TransactionDefinition transactionDefinition, boolean defaultRollback) {
this.testContext = testContext;
this.transactionManager = transactionManager;
this.transactionDefinition = transactionDefinition;
@@ -63,6 +65,8 @@ class TransactionContext {
this.flaggedForRollback = defaultRollback;
}
@Nullable
TransactionStatus getTransactionStatus() {
return this.transactionStatus;
}
@@ -83,7 +87,7 @@ class TransactionContext {
}
/**
* Start a new transaction for the configured {@linkplain #getTestContext test context}.
* Start a new transaction for the configured test context.
* <p>Only call this method if {@link #endTransaction} has been called or if no
* transaction has been previously started.
* @throws TransactionException if starting the transaction fails
@@ -102,9 +106,8 @@ class TransactionContext {
}
/**
* Immediately force a <em>commit</em> or <em>rollback</em> of the transaction
* for the configured {@linkplain #getTestContext test context}, according to
* the {@linkplain #isFlaggedForRollback rollback flag}.
* Immediately force a <em>commit</em> or <em>rollback</em> of the transaction for the
* configured test context, according to the {@linkplain #isFlaggedForRollback rollback flag}.
*/
void endTransaction() {
if (logger.isTraceEnabled()) {
@@ -133,4 +136,4 @@ class TransactionContext {
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -17,6 +17,7 @@
package org.springframework.test.context.transaction;
import org.springframework.core.NamedInheritableThreadLocal;
import org.springframework.lang.Nullable;
/**
* {@link InheritableThreadLocal}-based holder for the current {@link TransactionContext}.
@@ -26,18 +27,20 @@ import org.springframework.core.NamedInheritableThreadLocal;
*/
class TransactionContextHolder {
private static final ThreadLocal<TransactionContext> currentTransactionContext = new NamedInheritableThreadLocal<>(
"Test Transaction Context");
private static final ThreadLocal<TransactionContext> currentTransactionContext =
new NamedInheritableThreadLocal<>("Test Transaction Context");
static void setCurrentTransactionContext(@Nullable TransactionContext transactionContext) {
currentTransactionContext.set(transactionContext);
}
@Nullable
static TransactionContext getCurrentTransactionContext() {
return currentTransactionContext.get();
}
static void setCurrentTransactionContext(TransactionContext transactionContext) {
currentTransactionContext.set(transactionContext);
}
@Nullable
static TransactionContext removeCurrentTransactionContext() {
synchronized (currentTransactionContext) {
TransactionContext transactionContext = currentTransactionContext.get();

View File

@@ -31,6 +31,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.test.annotation.Commit;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.TestContext;
@@ -156,8 +157,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
*/
@Override
public void beforeTestMethod(final TestContext testContext) throws Exception {
final Method testMethod = testContext.getTestMethod();
final Class<?> testClass = testContext.getTestClass();
Method testMethod = testContext.getTestMethod();
Class<?> testClass = testContext.getTestClass();
Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null");
TransactionContext txContext = TransactionContextHolder.removeCurrentTransactionContext();
@@ -180,7 +181,6 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
}
tm = getTransactionManager(testContext, transactionAttribute.getQualifier());
Assert.state(tm != null, () -> String.format(
"Failed to retrieve PlatformTransactionManager for @Transactional test for test context %s.",
testContext));
@@ -212,7 +212,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
TransactionStatus transactionStatus = txContext.getTransactionStatus();
try {
// If the transaction is still active...
if ((transactionStatus != null) && !transactionStatus.isCompleted()) {
if (transactionStatus != null && !transactionStatus.isCompleted()) {
txContext.endTransaction();
}
}
@@ -306,6 +306,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
* @throws BeansException if an error occurs while retrieving the transaction manager
* @see #getTransactionManager(TestContext)
*/
@Nullable
protected PlatformTransactionManager getTransactionManager(TestContext testContext, String qualifier) {
// Look up by type and qualifier from @Transactional
if (StringUtils.hasText(qualifier)) {
@@ -344,6 +345,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
* exists in the ApplicationContext
* @see #getTransactionManager(TestContext, String)
*/
@Nullable
protected PlatformTransactionManager getTransactionManager(TestContext testContext) {
return TestContextTransactionUtils.retrieveTransactionManager(testContext, null);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -47,10 +47,6 @@ public abstract class TestContextResourceUtils {
private static final String SLASH = "/";
private TestContextResourceUtils() {
/* prevent instantiation */
}
/**
* Convert the supplied paths to classpath resource paths.
*
@@ -65,7 +61,6 @@ public abstract class TestContextResourceUtils {
* {@link ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
* {@link ResourceUtils#FILE_URL_PREFIX file:}, {@code http:}, etc.) will be
* {@link StringUtils#cleanPath cleaned} but otherwise unmodified.
*
* @param clazz the class with which the paths are associated
* @param paths the paths to be converted
* @return a new array of converted resource paths
@@ -79,8 +74,8 @@ public abstract class TestContextResourceUtils {
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}
else if (!ResourcePatternUtils.isUrl(path)) {
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + SLASH
+ StringUtils.cleanPath(ClassUtils.classPackageAsResourcePath(clazz) + SLASH + path);
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + SLASH +
StringUtils.cleanPath(ClassUtils.classPackageAsResourcePath(clazz) + SLASH + path);
}
else {
convertedPaths[i] = StringUtils.cleanPath(path);
@@ -92,7 +87,6 @@ public abstract class TestContextResourceUtils {
/**
* Convert the supplied paths to an array of {@link Resource} handles using
* the given {@link ResourceLoader}.
*
* @param resourceLoader the {@code ResourceLoader} to use to convert the paths
* @param paths the paths to be converted
* @return a new array of resources
@@ -106,7 +100,6 @@ public abstract class TestContextResourceUtils {
/**
* Convert the supplied paths to a list of {@link Resource} handles using
* the given {@link ResourceLoader}.
*
* @param resourceLoader the {@code ResourceLoader} to use to convert the paths
* @param paths the paths to be converted
* @return a new list of resources

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.
@@ -20,7 +20,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.support.AnnotationConfigContextLoaderUtils;
@@ -80,7 +79,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
* @see #detectDefaultConfigurationClasses(Class)
*/
@Override
public void processContextConfiguration(@Nullable ContextConfigurationAttributes configAttributes) {
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) {
if (!configAttributes.hasClasses() && isGenerateDefaultLocations()) {
configAttributes.setClasses(detectDefaultConfigurationClasses(configAttributes.getDeclaringClass()));
}

View File

@@ -99,7 +99,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
* @since 4.1
*/
public WebMergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
@Nullable Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
String resourceBasePath, ContextLoader contextLoader,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
@@ -135,7 +135,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
* @since 4.3
*/
public WebMergedContextConfiguration(Class<?> testClass, @Nullable String[] locations, @Nullable Class<?>[] classes,
@Nullable Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
@Nullable Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
@Nullable String[] activeProfiles, @Nullable String[] propertySourceLocations, @Nullable String[] propertySourceProperties,
@Nullable Set<ContextCustomizer> contextCustomizers, String resourceBasePath, ContextLoader contextLoader,
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, @Nullable MergedContextConfiguration parent) {
@@ -206,7 +206,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
.append("propertySourceProperties", ObjectUtils.nullSafeToString(getPropertySourceProperties()))
.append("contextCustomizers", getContextCustomizers())
.append("resourceBasePath", getResourceBasePath())
.append("contextLoader", nullSafeToString(getContextLoader()))
.append("contextLoader", nullSafeClassName(getContextLoader()))
.append("parent", getParent())
.toString();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -16,7 +16,10 @@
package org.springframework.test.context.web.socket;
import javax.servlet.ServletContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.web.context.WebApplicationContext;
@@ -35,12 +38,15 @@ class MockServerContainerContextCustomizer implements ContextCustomizer {
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
if (context instanceof WebApplicationContext) {
WebApplicationContext wac = (WebApplicationContext) context;
wac.getServletContext().setAttribute("javax.websocket.server.ServerContainer", new MockServerContainer());
ServletContext sc = wac.getServletContext();
if (sc != null) {
sc.setAttribute("javax.websocket.server.ServerContainer", new MockServerContainer());
}
}
}
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
return (this == other || (other != null && getClass() == other.getClass()));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -50,7 +50,8 @@ public class JdbcTestUtils {
* @return the number of rows in the table
*/
public static int countRowsInTable(JdbcTemplate jdbcTemplate, String tableName) {
return jdbcTemplate.queryForObject("SELECT COUNT(0) FROM " + tableName, Integer.class);
Integer result = jdbcTemplate.queryForObject("SELECT COUNT(0) FROM " + tableName, Integer.class);
return (result != null ? result : 0);
}
/**
@@ -72,7 +73,8 @@ public class JdbcTestUtils {
if (StringUtils.hasText(whereClause)) {
sql += " WHERE " + whereClause;
}
return jdbcTemplate.queryForObject(sql, Integer.class);
Integer result = jdbcTemplate.queryForObject(sql, Integer.class);
return (result != null ? result : 0);
}
/**
@@ -112,14 +114,14 @@ public class JdbcTestUtils {
* optionally the scale.
* @return the number of rows deleted from the table
*/
public static int deleteFromTableWhere(JdbcTemplate jdbcTemplate, String tableName, String whereClause,
Object... args) {
public static int deleteFromTableWhere(
JdbcTemplate jdbcTemplate, String tableName, String whereClause, Object... args) {
String sql = "DELETE FROM " + tableName;
if (StringUtils.hasText(whereClause)) {
sql += " WHERE " + whereClause;
}
int rowCount = (args != null && args.length > 0 ? jdbcTemplate.update(sql, args) : jdbcTemplate.update(sql));
int rowCount = (args.length > 0 ? jdbcTemplate.update(sql, args) : jdbcTemplate.update(sql));
if (logger.isInfoEnabled()) {
logger.info("Deleted " + rowCount + " rows from table " + tableName);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -16,6 +16,7 @@
package org.springframework.test.util;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -50,7 +51,7 @@ public abstract class AssertionErrors {
* @param expected expected value
* @param actual actual value
*/
public static void fail(String message, Object expected, Object actual) {
public static void fail(String message, @Nullable Object expected, @Nullable Object actual) {
throw new AssertionError(message + " expected:<" + expected + "> but was:<" + actual + ">");
}
@@ -76,7 +77,7 @@ public abstract class AssertionErrors {
* @param expected the expected value
* @param actual the actual value
*/
public static void assertEquals(String message, Object expected, Object actual) {
public static void assertEquals(String message, @Nullable Object expected, @Nullable Object actual) {
if (!ObjectUtils.nullSafeEquals(expected, actual)) {
fail(message, ObjectUtils.nullSafeToString(expected), ObjectUtils.nullSafeToString(actual));
}
@@ -92,7 +93,7 @@ public abstract class AssertionErrors {
* @param expected the expected value
* @param actual the actual value
*/
public static void assertNotEquals(String message, Object expected, Object actual) {
public static void assertNotEquals(String message, @Nullable Object expected, @Nullable Object actual) {
if (ObjectUtils.nullSafeEquals(expected, actual)) {
throw new AssertionError(message + " was not expected to be:" +
"<" + ObjectUtils.nullSafeToString(actual) + ">");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.
@@ -34,7 +34,6 @@ public class JsonExpectationsHelper {
* are "similar" - i.e. they contain the same attribute-value pairs
* regardless of formatting with a lenient checking (extensible, and non-strict
* array ordering).
*
* @param expected the expected JSON content
* @param actual the actual JSON content
* @since 4.1
@@ -48,13 +47,11 @@ public class JsonExpectationsHelper {
* Parse the expected and actual strings as JSON and assert the two
* are "similar" - i.e. they contain the same attribute-value pairs
* regardless of formatting.
*
* <p>Can compare in two modes, depending on {@code strict} parameter value:
* <ul>
* <li>{@code true}: strict checking. Not extensible, and strict array ordering.</li>
* <li>{@code false}: lenient checking. Extensible, and non-strict array ordering.</li>
* <li>{@code true}: strict checking. Not extensible, and strict array ordering.</li>
* <li>{@code false}: lenient checking. Extensible, and non-strict array ordering.</li>
* </ul>
*
* @param expected the expected JSON content
* @param actual the actual JSON content
* @param strict enables strict checking
@@ -69,7 +66,6 @@ public class JsonExpectationsHelper {
* are "not similar" - i.e. they contain different attribute-value pairs
* regardless of formatting with a lenient checking (extensible, and non-strict
* array ordering).
*
* @param expected the expected JSON content
* @param actual the actual JSON content
* @since 4.1
@@ -83,13 +79,11 @@ public class JsonExpectationsHelper {
* Parse the expected and actual strings as JSON and assert the two
* are "not similar" - i.e. they contain different attribute-value pairs
* regardless of formatting.
*
* <p>Can compare in two modes, depending on {@code strict} parameter value:
* <ul>
* <li>{@code true}: strict checking. Not extensible, and strict array ordering.</li>
* <li>{@code false}: lenient checking. Extensible, and non-strict array ordering.</li>
* <li>{@code true}: strict checking. Not extensible, and strict array ordering.</li>
* <li>{@code false}: lenient checking. Extensible, and non-strict array ordering.</li>
* </ul>
*
* @param expected the expected JSON content
* @param actual the actual JSON content
* @param strict enables strict checking

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -22,6 +22,7 @@ import java.util.Map;
import com.jayway.jsonpath.JsonPath;
import org.hamcrest.Matcher;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -95,7 +96,7 @@ public class JsonPathExpectationsHelper {
* @param content the JSON content
* @param expectedValue the expected value
*/
public void assertValue(String content, Object expectedValue) {
public void assertValue(String content, @Nullable Object expectedValue) {
Object actualValue = evaluateJsonPath(content);
if ((actualValue instanceof List) && !(expectedValue instanceof List)) {
@SuppressWarnings("rawtypes")
@@ -231,11 +232,12 @@ public class JsonPathExpectationsHelper {
assertTrue(failureReason("a non-empty value", value), !ObjectUtils.isEmpty(value));
}
private String failureReason(String expectedDescription, Object value) {
private String failureReason(String expectedDescription, @Nullable Object value) {
return String.format("Expected %s at JSON path \"%s\" but found: %s", expectedDescription, this.expression,
ObjectUtils.nullSafeToString(StringUtils.quoteIfString(value)));
}
@Nullable
private Object evaluateJsonPath(String content) {
String message = "No value at JSON path \"" + this.expression + "\"";
try {
@@ -256,6 +258,7 @@ public class JsonPathExpectationsHelper {
}
}
@Nullable
private Object assertExistsAndReturn(String content) {
Object value = evaluateJsonPath(content);
String reason = "No value at JSON path \"" + this.expression + "\"";

View File

@@ -100,7 +100,7 @@ public abstract class MetaAnnotationUtils {
*/
@Nullable
private static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(
Class<?> clazz, Set<Annotation> visited, Class<T> annotationType) {
@Nullable Class<?> clazz, Set<Annotation> visited, Class<T> annotationType) {
Assert.notNull(annotationType, "Annotation type must not be null");
if (clazz == null || Object.class == clazz) {
@@ -187,7 +187,7 @@ public abstract class MetaAnnotationUtils {
*/
@SuppressWarnings("unchecked")
@Nullable
private static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(Class<?> clazz,
private static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(@Nullable Class<?> clazz,
Set<Annotation> visited, Class<? extends Annotation>... annotationTypes) {
assertNonEmptyAnnotationTypeArray(annotationTypes, "The list of annotation types must not be empty");
@@ -298,7 +298,7 @@ public abstract class MetaAnnotationUtils {
}
public AnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
Annotation composedAnnotation, T annotation) {
@Nullable Annotation composedAnnotation, T annotation) {
Assert.notNull(rootDeclaringClass, "'rootDeclaringClass' must not be null");
Assert.notNull(annotation, "Annotation must not be null");
@@ -349,6 +349,7 @@ public abstract class MetaAnnotationUtils {
return this.composedAnnotation;
}
@Nullable
public Class<? extends Annotation> getComposedAnnotationType() {
return (this.composedAnnotation != null ? this.composedAnnotation.annotationType() : null);
}
@@ -380,7 +381,7 @@ public abstract class MetaAnnotationUtils {
}
public UntypedAnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
Annotation composedAnnotation, Annotation annotation) {
@Nullable Annotation composedAnnotation, Annotation annotation) {
super(rootDeclaringClass, declaringClass, composedAnnotation, annotation);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -81,7 +81,7 @@ public class ReflectionTestUtils {
* @param name the name of the field to set; never {@code null}
* @param value the value to set
*/
public static void setField(Object targetObject, String name, Object value) {
public static void setField(Object targetObject, String name, @Nullable Object value) {
setField(targetObject, name, value, null);
}
@@ -97,7 +97,7 @@ public class ReflectionTestUtils {
* @param type the type of the field to set; may be {@code null} if
* {@code name} is specified
*/
public static void setField(Object targetObject, @Nullable String name, Object value, Class<?> type) {
public static void setField(Object targetObject, @Nullable String name, @Nullable Object value, @Nullable Class<?> type) {
setField(targetObject, null, name, value, type);
}
@@ -112,7 +112,7 @@ public class ReflectionTestUtils {
* @param value the value to set
* @since 4.2
*/
public static void setField(Class<?> targetClass, String name, Object value) {
public static void setField(Class<?> targetClass, String name, @Nullable Object value) {
setField(null, targetClass, name, value, null);
}
@@ -131,7 +131,9 @@ public class ReflectionTestUtils {
* {@code name} is specified
* @since 4.2
*/
public static void setField(Class<?> targetClass, @Nullable String name, Object value, @Nullable Class<?> type) {
public static void setField(
Class<?> targetClass, @Nullable String name, @Nullable Object value, @Nullable Class<?> type) {
setField(null, targetClass, name, value, type);
}
@@ -161,9 +163,11 @@ public class ReflectionTestUtils {
* @see ReflectionUtils#setField(Field, Object, Object)
* @see AopTestUtils#getUltimateTargetObject(Object)
*/
public static void setField(@Nullable Object targetObject, @Nullable Class<?> targetClass, @Nullable String name, Object value, @Nullable Class<?> type) {
public static void setField(@Nullable Object targetObject, @Nullable Class<?> targetClass,
@Nullable String name, @Nullable Object value, @Nullable Class<?> type) {
Assert.isTrue(targetObject != null || targetClass != null,
"Either targetObject or targetClass for the field must be specified");
"Either targetObject or targetClass for the field must be specified");
Object ultimateTarget = (targetObject != null ? AopTestUtils.getUltimateTargetObject(targetObject) : null);
@@ -198,6 +202,7 @@ public class ReflectionTestUtils {
* @return the field's current value
* @see #getField(Class, String)
*/
@Nullable
public static Object getField(Object targetObject, String name) {
return getField(targetObject, null, name);
}
@@ -214,6 +219,7 @@ public class ReflectionTestUtils {
* @since 4.2
* @see #getField(Object, String)
*/
@Nullable
public static Object getField(Class<?> targetClass, String name) {
return getField(null, targetClass, name);
}
@@ -242,6 +248,7 @@ public class ReflectionTestUtils {
* @see ReflectionUtils#getField(Field, Object)
* @see AopTestUtils#getUltimateTargetObject(Object)
*/
@Nullable
public static Object getField(@Nullable Object targetObject, @Nullable Class<?> targetClass, String name) {
Assert.isTrue(targetObject != null || targetClass != null,
"Either targetObject or targetClass for the field must be specified");
@@ -311,7 +318,7 @@ public class ReflectionTestUtils {
* @see ReflectionUtils#makeAccessible(Method)
* @see ReflectionUtils#invokeMethod(Method, Object, Object[])
*/
public static void invokeSetterMethod(Object target, String name, Object value, Class<?> type) {
public static void invokeSetterMethod(Object target, String name, @Nullable Object value, @Nullable Class<?> type) {
Assert.notNull(target, "Target object must not be null");
Assert.hasText(name, "Method name must not be empty");
Class<?>[] paramTypes = (type != null ? new Class<?>[] {type} : null);
@@ -361,6 +368,7 @@ public class ReflectionTestUtils {
* @see ReflectionUtils#makeAccessible(Method)
* @see ReflectionUtils#invokeMethod(Method, Object, Object[])
*/
@Nullable
public static Object invokeGetterMethod(Object target, String name) {
Assert.notNull(target, "Target object must not be null");
Assert.hasText(name, "Method name must not be empty");
@@ -404,7 +412,7 @@ public class ReflectionTestUtils {
*/
@SuppressWarnings("unchecked")
@Nullable
public static <T> T invokeMethod(Object target, String name, @Nullable Object... args) {
public static <T> T invokeMethod(Object target, String name, Object... args) {
Assert.notNull(target, "Target object must not be null");
Assert.hasText(name, "Method name must not be empty");
@@ -428,13 +436,13 @@ public class ReflectionTestUtils {
}
}
private static String safeToString(Object target) {
private static String safeToString(@Nullable Object target) {
try {
return String.format("target object [%s]", target);
}
catch (Exception ex) {
return String.format("target of type [%s] whose toString() method threw [%s]",
(target != null ? target.getClass().getName() : "unknown"), ex);
(target != null ? target.getClass().getName() : "unknown"), ex);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -19,7 +19,6 @@ package org.springframework.test.util;
import java.io.ByteArrayInputStream;
import java.util.Collections;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -75,7 +74,7 @@ public class XpathExpectationsHelper {
}
private XPathExpression compileXpathExpression(String expression, Map<String, String> namespaces)
private XPathExpression compileXpathExpression(String expression, @Nullable Map<String, String> namespaces)
throws XPathExpressionException {
SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
@@ -96,7 +95,9 @@ public class XpathExpectationsHelper {
* Parse the content, evaluate the XPath expression as a {@link Node},
* and assert it with the given {@code Matcher<Node>}.
*/
public void assertNode(byte[] content, String encoding, final Matcher<? super Node> matcher) throws Exception {
public void assertNode(byte[] content, @Nullable String encoding, final Matcher<? super Node> matcher)
throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertThat("XPath " + this.expression, node, matcher);
@@ -108,7 +109,7 @@ public class XpathExpectationsHelper {
* @param encoding optional content encoding, if provided as metadata (e.g. in HTTP headers)
* @return the parsed document
*/
protected Document parseXmlByteArray(byte[] xml, String encoding) throws Exception {
protected Document parseXmlByteArray(byte[] xml, @Nullable String encoding) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(this.hasNamespaces);
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
@@ -124,6 +125,7 @@ public class XpathExpectationsHelper {
* @throws XPathExpressionException
*/
@SuppressWarnings("unchecked")
@Nullable
protected <T> T evaluateXpath(Document document, QName evaluationType, Class<T> expectedClass)
throws XPathExpressionException {
@@ -134,7 +136,7 @@ public class XpathExpectationsHelper {
* Apply the XPath expression and assert the resulting content exists.
* @throws Exception if content parsing or expression evaluation fails
*/
public void exists(byte[] content, String encoding) throws Exception {
public void exists(byte[] content, @Nullable String encoding) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertTrue("XPath " + this.expression + " does not exist", node != null);
@@ -144,7 +146,7 @@ public class XpathExpectationsHelper {
* Apply the XPath expression and assert the resulting content does not exist.
* @throws Exception if content parsing or expression evaluation fails
*/
public void doesNotExist(byte[] content, String encoding) throws Exception {
public void doesNotExist(byte[] content, @Nullable String encoding) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
assertTrue("XPath " + this.expression + " exists", node == null);
@@ -155,20 +157,22 @@ public class XpathExpectationsHelper {
* given Hamcrest matcher.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNodeCount(byte[] content, String encoding, Matcher<Integer> matcher) throws Exception {
public void assertNodeCount(byte[] content, @Nullable String encoding, Matcher<Integer> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
assertThat("nodeCount for XPath " + this.expression, nodeList.getLength(), matcher);
assertThat("nodeCount for XPath " + this.expression,
(nodeList != null ? nodeList.getLength() : 0), matcher);
}
/**
* Apply the XPath expression and assert the resulting content as an integer.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNodeCount(byte[] content, String encoding, int expectedCount) throws Exception {
public void assertNodeCount(byte[] content, @Nullable String encoding, int expectedCount) throws Exception {
Document document = parseXmlByteArray(content, encoding);
NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
assertEquals("nodeCount for XPath " + this.expression, expectedCount, nodeList.getLength());
assertEquals("nodeCount for XPath " + this.expression, expectedCount,
(nodeList != null ? nodeList.getLength() : 0));
}
/**
@@ -176,7 +180,7 @@ public class XpathExpectationsHelper {
* given Hamcrest matcher.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertString(byte[] content, String encoding, Matcher<? super String> matcher) throws Exception {
public void assertString(byte[] content, @Nullable String encoding, Matcher<? super String> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String result = evaluateXpath(document, XPathConstants.STRING, String.class);
assertThat("XPath " + this.expression, result, matcher);
@@ -186,7 +190,7 @@ public class XpathExpectationsHelper {
* Apply the XPath expression and assert the resulting content as a String.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertString(byte[] content, String encoding, String expectedValue) throws Exception {
public void assertString(byte[] content, @Nullable String encoding, String expectedValue) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
assertEquals("XPath " + this.expression, expectedValue, actual);
@@ -197,7 +201,7 @@ public class XpathExpectationsHelper {
* given Hamcrest matcher.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNumber(byte[] content, String encoding, Matcher<? super Double> matcher) throws Exception {
public void assertNumber(byte[] content, @Nullable String encoding, Matcher<? super Double> matcher) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Double result = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
assertThat("XPath " + this.expression, result, matcher);
@@ -207,7 +211,7 @@ public class XpathExpectationsHelper {
* Apply the XPath expression and assert the resulting content as a Double.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertNumber(byte[] content, String encoding, Double expectedValue) throws Exception {
public void assertNumber(byte[] content, @Nullable String encoding, Double expectedValue) throws Exception {
Document document = parseXmlByteArray(content, encoding);
Double actual = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
assertEquals("XPath " + this.expression, expectedValue, actual);
@@ -217,7 +221,7 @@ public class XpathExpectationsHelper {
* Apply the XPath expression and assert the resulting content as a Boolean.
* @throws Exception if content parsing or expression evaluation fails
*/
public void assertBoolean(byte[] content, String encoding, boolean expectedValue) throws Exception {
public void assertBoolean(byte[] content, @Nullable String encoding, boolean expectedValue) throws Exception {
Document document = parseXmlByteArray(content, encoding);
String actual = evaluateXpath(document, XPathConstants.STRING, String.class);
assertEquals("XPath " + this.expression, expectedValue, Boolean.parseBoolean(actual));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -48,30 +48,30 @@ public abstract class ModelAndViewAssert {
* Checks whether the model value under the given {@code modelName}
* exists and checks it type, based on the {@code expectedType}. If the
* model entry exists and the type matches, the model value is returned.
*
* @param mav ModelAndView to test against (never {@code null})
* @param modelName name of the object to add to the model (never
* {@code null})
* @param modelName name of the object to add to the model (never {@code null})
* @param expectedType expected type of the model value
* @return the model value
*/
@SuppressWarnings("unchecked")
public static <T> T assertAndReturnModelAttributeOfType(ModelAndView mav, String modelName, Class<T> expectedType) {
assertTrue("ModelAndView is null", mav != null);
assertTrue("Model is null", mav.getModel() != null);
Object obj = mav.getModel().get(modelName);
assertTrue("Model attribute with name '" + modelName + "' is null", obj != null);
assertTrue("Model attribute is not of expected type '" + expectedType.getName() + "' but rather of type '"
+ obj.getClass().getName() + "'", expectedType.isAssignableFrom(obj.getClass()));
if (mav == null) {
fail("ModelAndView is null");
}
Map<String, Object> model = mav.getModel();
Object obj = model.get(modelName);
if (obj == null) {
fail("Model attribute with name '" + modelName + "' is null");
}
assertTrue("Model attribute is not of expected type '" + expectedType.getName() + "' but rather of type '" +
obj.getClass().getName() + "'", expectedType.isAssignableFrom(obj.getClass()));
return (T) obj;
}
/**
* Compare each individual entry in a list, without first sorting the lists.
*
* @param mav ModelAndView to test against (never {@code null})
* @param modelName name of the object to add to the model (never
* {@code null})
* @param modelName name of the object to add to the model (never {@code null})
* @param expectedList the expected list
*/
@SuppressWarnings("rawtypes")
@@ -87,55 +87,53 @@ public abstract class ModelAndViewAssert {
/**
* Assert whether or not a model attribute is available.
*
* @param mav ModelAndView to test against (never {@code null})
* @param modelName name of the object to add to the model (never
* {@code null})
* @param modelName name of the object to add to the model (never {@code null})
*/
public static void assertModelAttributeAvailable(ModelAndView mav, String modelName) {
assertTrue("ModelAndView is null", mav != null);
assertTrue("Model is null", mav.getModel() != null);
assertTrue("Model attribute with name '" + modelName + "' is not available",
mav.getModel().containsKey(modelName));
if (mav == null) {
fail("ModelAndView is null");
}
Map<String, Object> model = mav.getModel();
assertTrue("Model attribute with name '" + modelName + "' is not available", model.containsKey(modelName));
}
/**
* Compare a given {@code expectedValue} to the value from the model
* bound under the given {@code modelName}.
*
* @param mav ModelAndView to test against (never {@code null})
* @param modelName name of the object to add to the model (never
* {@code null})
* @param modelName name of the object to add to the model (never {@code null})
* @param expectedValue the model value
*/
public static void assertModelAttributeValue(ModelAndView mav, String modelName, Object expectedValue) {
assertTrue("ModelAndView is null", mav != null);
Object modelValue = assertAndReturnModelAttributeOfType(mav, modelName, Object.class);
assertTrue("Model value with name '" + modelName + "' is not the same as the expected value which was '"
+ expectedValue + "'", modelValue.equals(expectedValue));
assertTrue("Model value with name '" + modelName + "' is not the same as the expected value which was '" +
expectedValue + "'", modelValue.equals(expectedValue));
}
/**
* Inspect the {@code expectedModel} to see if all elements in the
* model appear and are equal.
*
* @param mav ModelAndView to test against (never {@code null})
* @param expectedModel the expected model
*/
public static void assertModelAttributeValues(ModelAndView mav, Map<String, Object> expectedModel) {
assertTrue("ModelAndView is null", mav != null);
assertTrue("Model is null", mav.getModel() != null);
if (mav == null) {
fail("ModelAndView is null");
}
Map<String, Object> model = mav.getModel();
if (!mav.getModel().keySet().equals(expectedModel.keySet())) {
if (!model.keySet().equals(expectedModel.keySet())) {
StringBuilder sb = new StringBuilder("Keyset of expected model does not match.\n");
appendNonMatchingSetsErrorMessage(expectedModel.keySet(), mav.getModel().keySet(), sb);
appendNonMatchingSetsErrorMessage(expectedModel.keySet(), model.keySet(), sb);
fail(sb.toString());
}
StringBuilder sb = new StringBuilder();
for (String modelName : mav.getModel().keySet()) {
for (String modelName : model.keySet()) {
Object assertionValue = expectedModel.get(modelName);
Object mavValue = mav.getModel().get(modelName);
Object mavValue = model.get(modelName);
if (!assertionValue.equals(mavValue)) {
sb.append("Value under name '").append(modelName).append("' differs, should have been '").append(
assertionValue).append("' but was '").append(mavValue).append("'\n");
@@ -151,18 +149,15 @@ public abstract class ModelAndViewAssert {
/**
* Compare each individual entry in a list after having sorted both lists
* (optionally using a comparator).
*
* @param mav ModelAndView to test against (never {@code null})
* @param modelName name of the object to add to the model (never
* {@code null})
* @param modelName name of the object to add to the model (never {@code null})
* @param expectedList the expected list
* @param comparator the comparator to use (may be {@code null}). If
* not specifying the comparator, both lists will be sorted not using any
* comparator.
* @param comparator the comparator to use (may be {@code null}). If not
* specifying the comparator, both lists will be sorted not using any comparator.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void assertSortAndCompareListModelAttribute(ModelAndView mav, String modelName, List expectedList,
Comparator comparator) {
public static void assertSortAndCompareListModelAttribute(
ModelAndView mav, String modelName, List expectedList, Comparator comparator) {
assertTrue("ModelAndView is null", mav != null);
List modelList = assertAndReturnModelAttributeOfType(mav, modelName, List.class);
@@ -187,18 +182,20 @@ public abstract class ModelAndViewAssert {
/**
* Check to see if the view name in the ModelAndView matches the given
* {@code expectedName}.
*
* @param mav ModelAndView to test against (never {@code null})
* @param expectedName the name of the model value
*/
public static void assertViewName(ModelAndView mav, String expectedName) {
assertTrue("ModelAndView is null", mav != null);
if (mav == null) {
fail("ModelAndView is null");
}
assertTrue("View name is not equal to '" + expectedName + "' but was '" + mav.getViewName() + "'",
ObjectUtils.nullSafeEquals(expectedName, mav.getViewName()));
}
private static void appendNonMatchingSetsErrorMessage(Set<String> assertionSet, Set<String> incorrectSet,
StringBuilder sb) {
private static void appendNonMatchingSetsErrorMessage(
Set<String> assertionSet, Set<String> incorrectSet, StringBuilder sb) {
Set<String> tempSet = new HashSet<>();
tempSet.addAll(incorrectSet);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -98,8 +98,10 @@ public class ContentRequestMatchers {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
MediaType actualContentType = request.getHeaders().getContentType();
assertTrue("Content type not set", actualContentType != null);
assertTrue("Content type [" + actualContentType + "] is not compatible with [" + contentType + "]",
actualContentType.isCompatibleWith(contentType));
if (actualContentType != null) {
assertTrue("Content type [" + actualContentType + "] is not compatible with [" + contentType + "]",
actualContentType.isCompatibleWith(contentType));
}
}
};
}

View File

@@ -180,8 +180,10 @@ public abstract class MockRestRequestMatchers {
@Override
public void match(ClientHttpRequest request) {
assertValueCount("header", name, request.getHeaders(), matchers.length);
for (int i = 0 ; i < matchers.length; i++) {
assertThat("Request header", request.getHeaders().get(name).get(i), matchers[i]);
List<String> headerValues = request.getHeaders().get(name);
Assert.state(headerValues != null, "No header values");
for (int i = 0; i < matchers.length; i++) {
assertThat("Request header [" + name + "]", headerValues.get(i), matchers[i]);
}
}
};
@@ -195,9 +197,10 @@ public abstract class MockRestRequestMatchers {
@Override
public void match(ClientHttpRequest request) {
assertValueCount("header", name, request.getHeaders(), expectedValues.length);
List<String> headerValues = request.getHeaders().get(name);
Assert.state(headerValues != null, "No header values");
for (int i = 0 ; i < expectedValues.length; i++) {
assertEquals("Request header + [" + name + "]",
expectedValues[i], request.getHeaders().get(name).get(i));
assertEquals("Request header [" + name + "]", expectedValues[i], headerValues.get(i));
}
}
};

View File

@@ -43,9 +43,7 @@ class DefaultRouterFunctionSpec extends AbstractMockServerSpec<WebTestClient.Rou
@Override
public WebTestClient.RouterFunctionSpec handlerStrategies(HandlerStrategies handlerStrategies) {
if (handlerStrategies != null) {
this.handlerStrategies = handlerStrategies;
}
this.handlerStrategies = handlerStrategies;
return this;
}

View File

@@ -50,11 +50,9 @@ import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriBuilder;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.test.util.AssertionErrors.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.springframework.web.reactive.function.BodyExtractors.toFlux;
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
import static java.nio.charset.StandardCharsets.*;
import static org.springframework.test.util.AssertionErrors.*;
import static org.springframework.web.reactive.function.BodyExtractors.*;
/**
* Default implementation of {@link WebTestClient}.
@@ -73,7 +71,7 @@ class DefaultWebTestClient implements WebTestClient {
private final AtomicLong requestIndex = new AtomicLong();
DefaultWebTestClient(WebClient.Builder clientBuilder, ClientHttpConnector connector, Duration timeout) {
DefaultWebTestClient(WebClient.Builder clientBuilder, ClientHttpConnector connector, @Nullable Duration timeout) {
Assert.notNull(clientBuilder, "WebClient.Builder is required");
this.wiretapConnector = new WiretapConnector(connector);
this.webClient = clientBuilder.clientConnector(this.wiretapConnector).build();
@@ -179,15 +177,13 @@ class DefaultWebTestClient implements WebTestClient {
private final String requestId;
DefaultRequestBodySpec(WebClient.RequestBodySpec spec, String uriTemplate) {
DefaultRequestBodySpec(WebClient.RequestBodySpec spec, @Nullable String uriTemplate) {
this.bodySpec = spec;
this.uriTemplate = uriTemplate;
this.requestId = String.valueOf(requestIndex.incrementAndGet());
this.bodySpec.header(WebTestClient.WEBTESTCLIENT_REQUEST_ID, this.requestId);
}
@Override
public RequestBodySpec header(String headerName, String... headerValues) {
this.bodySpec.header(headerName, headerValues);
@@ -276,7 +272,6 @@ class DefaultWebTestClient implements WebTestClient {
ExchangeResult exchangeResult = wiretapConnector.claimRequest(this.requestId);
return new DefaultResponseSpec(exchangeResult, clientResponse, this.uriTemplate, getTimeout());
}
}
@@ -286,7 +281,6 @@ class DefaultWebTestClient implements WebTestClient {
private final Duration timeout;
UndecodedExchangeResult(ExchangeResult result, ClientResponse response,
String uriTemplate, Duration timeout) {
@@ -295,7 +289,6 @@ class DefaultWebTestClient implements WebTestClient {
this.timeout = timeout;
}
@SuppressWarnings("unchecked")
public <T> EntityExchangeResult<T> decode(ResolvableType bodyType) {
T body = (T) this.response.body(toMono(bodyType)).block(this.timeout);
@@ -318,7 +311,6 @@ class DefaultWebTestClient implements WebTestClient {
byte[] body = (resource != null ? resource.getByteArray() : null);
return new EntityExchangeResult<>(this, body);
}
}
@@ -326,7 +318,6 @@ class DefaultWebTestClient implements WebTestClient {
private final UndecodedExchangeResult result;
DefaultResponseSpec(ExchangeResult result, ClientResponse response, String uriTemplate, Duration timeout) {
this.result = new UndecodedExchangeResult(result, response, uriTemplate, timeout);
}
@@ -342,13 +333,15 @@ class DefaultWebTestClient implements WebTestClient {
}
@Override
@SuppressWarnings("unchecked")
public <B> BodySpec<B, ?> expectBody(Class<B> bodyType) {
return expectBody(ResolvableType.forClass(bodyType));
return (BodySpec<B, ?>) expectBody(ResolvableType.forClass(bodyType));
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public <B> BodySpec<B, ?> expectBody(ResolvableType bodyType) {
return new DefaultBodySpec<>(this.result.decode(bodyType));
return new DefaultBodySpec(this.result.decode(bodyType));
}
@Override
@@ -375,7 +368,6 @@ class DefaultWebTestClient implements WebTestClient {
public <T> FluxExchangeResult<T> returnResult(ResolvableType elementType) {
return this.result.decodeToFlux(elementType);
}
}
@@ -383,26 +375,23 @@ class DefaultWebTestClient implements WebTestClient {
private final EntityExchangeResult<B> result;
DefaultBodySpec(EntityExchangeResult<B> result) {
this.result = result;
}
protected EntityExchangeResult<B> getResult() {
return this.result;
}
@Override
public <T extends S> T isEqualTo(B expected) {
B actual = this.result.getResponseBody();
this.result.assertWithDiagnostics(() -> assertEquals("Response body", expected, actual));
this.result.assertWithDiagnostics(() ->
assertEquals("Response body", expected, this.result.getResponseBody()));
return self();
}
@Override
public <T extends S> T consumeWith(Consumer<EntityExchangeResult<B>> consumer) {
B actual = this.result.getResponseBody();
this.result.assertWithDiagnostics(() -> consumer.accept(this.result));
return self();
}
@@ -416,24 +405,21 @@ class DefaultWebTestClient implements WebTestClient {
public EntityExchangeResult<B> returnResult() {
return this.result;
}
}
private static class DefaultListBodySpec<E> extends DefaultBodySpec<List<E>, ListBodySpec<E>>
implements ListBodySpec<E> {
DefaultListBodySpec(EntityExchangeResult<List<E>> result) {
super(result);
}
@Override
public ListBodySpec<E> hasSize(int size) {
List<E> actual = getResult().getResponseBody();
String message = "Response body does not contain " + size + " elements";
getResult().assertWithDiagnostics(() -> assertEquals(message, size, actual.size()));
getResult().assertWithDiagnostics(() -> assertEquals(message, size, (actual != null ? actual.size() : 0)));
return this;
}
@@ -443,7 +429,7 @@ class DefaultWebTestClient implements WebTestClient {
List<E> expected = Arrays.asList(elements);
List<E> actual = getResult().getResponseBody();
String message = "Response body does not contain " + expected;
getResult().assertWithDiagnostics(() -> assertTrue(message, actual.containsAll(expected)));
getResult().assertWithDiagnostics(() -> assertTrue(message, (actual != null && actual.containsAll(expected))));
return this;
}
@@ -452,8 +438,8 @@ class DefaultWebTestClient implements WebTestClient {
public ListBodySpec<E> doesNotContain(E... elements) {
List<E> expected = Arrays.asList(elements);
List<E> actual = getResult().getResponseBody();
String message = "Response body should have contained " + expected;
getResult().assertWithDiagnostics(() -> assertTrue(message, !actual.containsAll(expected)));
String message = "Response body should not have contained " + expected;
getResult().assertWithDiagnostics(() -> assertTrue(message, (actual == null || !actual.containsAll(expected))));
return this;
}
@@ -461,7 +447,6 @@ class DefaultWebTestClient implements WebTestClient {
public EntityExchangeResult<List<E>> returnResult() {
return getResult();
}
}
@@ -471,13 +456,11 @@ class DefaultWebTestClient implements WebTestClient {
private final boolean isEmpty;
DefaultBodyContentSpec(EntityExchangeResult<byte[]> result) {
this.result = result;
this.isEmpty = (result.getResponseBody() == null);
}
@Override
public EntityExchangeResult<Void> isEmpty() {
this.result.assertWithDiagnostics(() -> assertTrue("Expected empty body", this.isEmpty));
@@ -502,14 +485,14 @@ class DefaultWebTestClient implements WebTestClient {
return new JsonPathAssertions(this, getBodyAsString(), expression, args);
}
@Nullable
private String getBodyAsString() {
if (this.isEmpty) {
return null;
byte[] body = this.result.getResponseBody();
if (body == null || body.length == 0) {
return "";
}
MediaType mediaType = this.result.getResponseHeaders().getContentType();
Charset charset = Optional.ofNullable(mediaType).map(MimeType::getCharset).orElse(UTF_8);
return new String(this.result.getResponseBody(), charset);
return new String(body, charset);
}
@Override
@@ -522,7 +505,6 @@ class DefaultWebTestClient implements WebTestClient {
public EntityExchangeResult<byte[]> returnResult() {
return this.result;
}
}
}

View File

@@ -16,6 +16,8 @@
package org.springframework.test.web.reactive.server;
import org.springframework.lang.Nullable;
/**
* {@code ExchangeResult} sub-class that exposes the response body fully
* extracted to a representation of type {@code <T>}.
@@ -30,7 +32,7 @@ public class EntityExchangeResult<T> extends ExchangeResult {
private final T body;
EntityExchangeResult(ExchangeResult result, T body) {
EntityExchangeResult(ExchangeResult result, @Nullable T body) {
super(result);
this.body = body;
}
@@ -39,6 +41,7 @@ public class EntityExchangeResult<T> extends ExchangeResult {
/**
* Return the entity extracted from the response body.
*/
@Nullable
public T getResponseBody() {
return this.body;
}

View File

@@ -31,6 +31,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
@@ -110,6 +111,7 @@ public class ExchangeResult {
/**
* Return the original URI template used to prepare the request, if any.
*/
@Nullable
public String getUriTemplate() {
return this.uriTemplate;
}
@@ -194,11 +196,7 @@ public class ExchangeResult {
}
private String getStatusReason() {
String reason = "";
if (getStatus() != null && getStatus().getReasonPhrase() != null) {
reason = getStatus().getReasonPhrase();
}
return reason;
return getStatus().getReasonPhrase();
}
private String formatHeaders(HttpHeaders headers, String delimiter) {
@@ -207,7 +205,7 @@ public class ExchangeResult {
.collect(Collectors.joining(delimiter));
}
private String formatBody(MediaType contentType, MonoProcessor<byte[]> body) {
private String formatBody(@Nullable MediaType contentType, MonoProcessor<byte[]> body) {
if (body.isSuccess()) {
byte[] bytes = body.block(Duration.ZERO);
if (bytes.length == 0) {

View File

@@ -23,9 +23,9 @@ import org.springframework.http.CacheControl;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import static org.springframework.test.util.AssertionErrors.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.springframework.test.util.AssertionErrors.*;
/**
* Assertions on headers of the response.
@@ -62,7 +62,9 @@ public class HeaderAssertions {
*/
public WebTestClient.ResponseSpec valueMatches(String name, String pattern) {
String value = getHeaders().getFirst(name);
assertTrue(getMessage(name) + " not found", value != null);
if (value == null) {
fail(getMessage(name) + " not found");
}
boolean match = Pattern.compile(pattern).matcher(value).matches();
String message = getMessage(name) + "=\'" + value + "\' does not match \'" + pattern + "\'";
this.exchangeResult.assertWithDiagnostics(() -> assertTrue(message, match));
@@ -122,7 +124,7 @@ public class HeaderAssertions {
return "Response header [" + headerName + "]";
}
private WebTestClient.ResponseSpec assertHeader(String name, Object expected, Object actual) {
private WebTestClient.ResponseSpec assertHeader(String name, @Nullable Object expected, @Nullable Object actual) {
this.exchangeResult.assertWithDiagnostics(() -> assertEquals(getMessage(name), expected, actual));
return this.responseSpec;
}

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.test.web.reactive.server;
import org.springframework.test.util.JsonPathExpectationsHelper;
/**
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> assertions.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -18,6 +18,7 @@ package org.springframework.test.web.servlet;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.FlashMap;
@@ -71,7 +72,7 @@ class DefaultMvcResult implements MvcResult {
return this.mockResponse;
}
public void setHandler(Object handler) {
public void setHandler(@Nullable Object handler) {
this.handler = handler;
}
@@ -80,7 +81,7 @@ class DefaultMvcResult implements MvcResult {
return this.handler;
}
public void setInterceptors(HandlerInterceptor... interceptors) {
public void setInterceptors(@Nullable HandlerInterceptor... interceptors) {
this.interceptors = interceptors;
}
@@ -98,7 +99,7 @@ class DefaultMvcResult implements MvcResult {
return this.resolvedException;
}
public void setModelAndView(ModelAndView mav) {
public void setModelAndView(@Nullable ModelAndView mav) {
this.modelAndView = mav;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -79,18 +79,16 @@ public final class MockMvc {
* Private constructor, not for direct instantiation.
* @see org.springframework.test.web.servlet.setup.MockMvcBuilders
*/
MockMvc(TestDispatcherServlet servlet, Filter[] filters, ServletContext servletContext) {
MockMvc(TestDispatcherServlet servlet, Filter... filters) {
Assert.notNull(servlet, "DispatcherServlet is required");
Assert.notNull(filters, "filters cannot be null");
Assert.noNullElements(filters, "filters cannot contain null values");
Assert.notNull(servletContext, "A ServletContext is required");
Assert.notNull(filters, "Filters cannot be null");
Assert.noNullElements(filters, "Filters cannot contain null values");
this.servlet = servlet;
this.filters = filters;
this.servletContext = servletContext;
this.servletContext = servlet.getServletContext();
}
/**
* A default request builder merged into every performed request.
* @see org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder#defaultRequest(RequestBuilder)
@@ -120,18 +118,14 @@ public final class MockMvc {
/**
* Perform a request and return a type that allows chaining further
* actions, such as asserting expectations, on the result.
*
* @param requestBuilder used to prepare the request to execute;
* see static factory methods in
* {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders}
*
* @return an instance of {@link ResultActions}; never {@code null}
*
* @see org.springframework.test.web.servlet.request.MockMvcRequestBuilders
* @see org.springframework.test.web.servlet.result.MockMvcResultMatchers
*/
public ResultActions perform(RequestBuilder requestBuilder) throws Exception {
if (this.defaultRequestBuilder != null) {
if (requestBuilder instanceof Mergeable) {
requestBuilder = (RequestBuilder) ((Mergeable) requestBuilder).merge(this.defaultRequestBuilder);
@@ -156,28 +150,23 @@ public final class MockMvc {
if (DispatcherType.ASYNC.equals(request.getDispatcherType()) &&
request.getAsyncContext() != null & !request.isAsyncStarted()) {
request.getAsyncContext().complete();
}
applyDefaultResultActions(mvcResult);
RequestContextHolder.setRequestAttributes(previousAttributes);
return new ResultActions() {
@Override
public ResultActions andExpect(ResultMatcher matcher) throws Exception {
matcher.match(mvcResult);
return this;
}
@Override
public ResultActions andDo(ResultHandler handler) throws Exception {
handler.handle(mvcResult);
return this;
}
@Override
public MvcResult andReturn() {
return mvcResult;
@@ -185,6 +174,7 @@ public final class MockMvc {
};
}
private void applyDefaultResultActions(MvcResult mvcResult) throws Exception {
for (ResultMatcher matcher : this.defaultResultMatchers) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -18,10 +18,10 @@ package org.springframework.test.web.servlet;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.core.NestedRuntimeException;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.web.context.WebApplicationContext;
@@ -43,9 +43,7 @@ public abstract class MockMvcBuilderSupport {
protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig,
WebApplicationContext webAppContext, RequestBuilder defaultRequestBuilder,
List<ResultMatcher> globalResultMatchers, List<ResultHandler> globalResultHandlers,
List<DispatcherServletCustomizer> dispatcherServletCustomizers) {
ServletContext servletContext = webAppContext.getServletContext();
@Nullable List<DispatcherServletCustomizer> dispatcherServletCustomizers) {
TestDispatcherServlet dispatcherServlet = new TestDispatcherServlet(webAppContext);
if (dispatcherServletCustomizers != null) {
@@ -61,7 +59,7 @@ public abstract class MockMvcBuilderSupport {
throw new MockMvcBuildException("Failed to initialize TestDispatcherServlet", ex);
}
MockMvc mockMvc = new MockMvc(dispatcherServlet, filters, servletContext);
MockMvc mockMvc = new MockMvc(dispatcherServlet, filters);
mockMvc.setDefaultRequest(defaultRequestBuilder);
mockMvc.setGlobalResultMatchers(globalResultMatchers);
mockMvc.setGlobalResultHandlers(globalResultHandlers);
@@ -69,6 +67,7 @@ public abstract class MockMvcBuilderSupport {
return mockMvc;
}
@SuppressWarnings("serial")
private static class MockMvcBuildException extends NestedRuntimeException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -60,7 +60,7 @@ public interface MvcResult {
/**
* Return the {@code ModelAndView} prepared by the handler.
* @return a {@code ModelAndView}, or {@code null}
* @return a {@code ModelAndView}, or {@code null} if none
*/
@Nullable
ModelAndView getModelAndView();
@@ -68,7 +68,7 @@ public interface MvcResult {
/**
* Return any exception raised by a handler and successfully resolved
* through a {@link HandlerExceptionResolver}.
* @return an exception, possibly {@code null}
* @return an exception, or {@code null} if none
*/
@Nullable
Exception getResolvedException();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -34,7 +34,6 @@ public interface RequestBuilder {
/**
* Build the request.
*
* @param servletContext the {@link ServletContext} to use to create the request
* @return the request
*/

View File

@@ -107,11 +107,13 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
Charset charset = getCharset();
String httpMethod = this.webRequest.getHttpMethod().name();
UriComponents uriComponents = uriComponents();
String path = uriComponents.getPath();
MockHttpServletRequest request = new HtmlUnitMockHttpServletRequest(
servletContext, httpMethod, uriComponents.getPath());
servletContext, httpMethod, (path != null ? path : ""));
parent(request, this.parentBuilder);
request.setServerName(uriComponents.getHost()); // needs to be first for additional headers
String host = uriComponents.getHost();
request.setServerName(host != null ? host : ""); // needs to be first for additional headers
authType(request);
request.setCharacterEncoding(charset.name());
content(request, charset);
@@ -125,7 +127,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
ports(uriComponents, request);
request.setProtocol("HTTP/1.1");
request.setQueryString(uriComponents.getQuery());
request.setScheme(uriComponents.getScheme());
String scheme = uriComponents.getScheme();
request.setScheme(scheme != null ? scheme : "");
request.setPathInfo(null);
return postProcess(request);
@@ -146,7 +149,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
return request;
}
private void parent(MockHttpServletRequest request, RequestBuilder parent) {
private void parent(MockHttpServletRequest request, @Nullable RequestBuilder parent) {
if (parent == null) {
return;
}
@@ -156,11 +159,13 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
// session
HttpSession parentSession = parentRequest.getSession(false);
if (parentSession != null) {
HttpSession localSession = request.getSession();
Assert.state(localSession != null, "No local HttpSession");
Enumeration<String> attrNames = parentSession.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = attrNames.nextElement();
Object attrValue = parentSession.getAttribute(attrName);
request.getSession().setAttribute(attrName, attrValue);
localSession.setAttribute(attrName, attrValue);
}
}
@@ -254,7 +259,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
}
}
else {
Assert.isTrue(uriComponents.getPath().startsWith(this.contextPath),
String path = uriComponents.getPath();
Assert.isTrue(path != null && path.startsWith(this.contextPath),
() -> "\"" + uriComponents.getPath() +
"\" should start with context path \"" + this.contextPath + "\"");
request.setContextPath(this.contextPath);
@@ -302,6 +308,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
}
}
@Nullable
private String header(String headerName) {
return this.webRequest.getAdditionalHeaders().get(headerName);
}
@@ -376,9 +383,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
private void servletPath(MockHttpServletRequest request, String requestPath) {
String servletPath = requestPath.substring(request.getContextPath().length());
if ("".equals(servletPath)) {
servletPath = null;
}
request.setServletPath(servletPath);
}
@@ -386,7 +390,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
if ("".equals(request.getPathInfo())) {
request.setPathInfo(null);
}
servletPath(request, uriComponents.getPath());
String path = uriComponents.getPath();
servletPath(request, (path != null ? path : ""));
}
private void ports(UriComponents uriComponents, MockHttpServletRequest request) {

View File

@@ -154,9 +154,6 @@ public final class MockMvcWebConnection implements WebConnection {
}
private void storeCookies(WebRequest webRequest, javax.servlet.http.Cookie[] cookies) {
if (cookies == null) {
return;
}
Date now = new Date();
CookieManager cookieManager = this.webClient.getCookieManager();
for (javax.servlet.http.Cookie cookie : cookies) {

View File

@@ -30,10 +30,10 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import org.springframework.beans.Mergeable;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -173,7 +173,7 @@ public class MockHttpServletRequestBuilder
Assert.isTrue(contextPath.startsWith("/"), "Context path must start with a '/'");
Assert.isTrue(!contextPath.endsWith("/"), "Context path must not end with a '/'");
}
this.contextPath = (contextPath != null ? contextPath : "");
this.contextPath = contextPath;
return this;
}
@@ -195,7 +195,7 @@ public class MockHttpServletRequestBuilder
Assert.isTrue(servletPath.startsWith("/"), "Servlet path must start with a '/'");
Assert.isTrue(!servletPath.endsWith("/"), "Servlet path must not end with a '/'");
}
this.servletPath = (servletPath != null ? servletPath : "");
this.servletPath = servletPath;
return this;
}
@@ -311,9 +311,8 @@ public class MockHttpServletRequestBuilder
* @param httpHeaders the headers and values to add
*/
public MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders) {
for (String name : httpHeaders.keySet()) {
Object[] values = ObjectUtils.toObjectArray(httpHeaders.get(name).toArray());
addToMultiValueMap(this.headers, name, values);
for (Map.Entry<String, List<String>> entry : httpHeaders.entrySet()) {
this.headers.addAll(entry.getKey(), entry.getValue());
}
return this;
}
@@ -654,7 +653,9 @@ public class MockHttpServletRequestBuilder
request.setAttribute(name, this.requestAttributes.get(name));
}
for (String name : this.sessionAttributes.keySet()) {
request.getSession().setAttribute(name, this.sessionAttributes.get(name));
HttpSession session = request.getSession();
Assert.state(session != null, "No HttpSession");
session.setAttribute(name, this.sessionAttributes.get(name));
}
FlashMap flashMap = new FlashMap();
@@ -739,10 +740,7 @@ public class MockHttpServletRequestBuilder
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
flashMapManager = wac.getBean(DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
}
catch (IllegalStateException ex) {
// ignore
}
catch (NoSuchBeanDefinitionException ex) {
catch (IllegalStateException | NoSuchBeanDefinitionException ex) {
// ignore
}
return (flashMapManager != null ? flashMapManager : new SessionFlashMapManager());
@@ -752,8 +750,6 @@ public class MockHttpServletRequestBuilder
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
for (RequestPostProcessor postProcessor : this.postProcessors) {
request = postProcessor.postProcessRequest(request);
Assert.state(request != null,
() -> "Post-processor [" + postProcessor.getClass().getName() + "] returned null");
}
return request;
}

View File

@@ -77,7 +77,9 @@ public class ContentResultMatchers {
return result -> {
String actual = result.getResponse().getContentType();
assertTrue("Content type not set", actual != null);
assertEquals("Content type", contentType, MediaType.parseMediaType(actual));
if (actual != null) {
assertEquals("Content type", contentType, MediaType.parseMediaType(actual));
}
};
}
@@ -97,9 +99,11 @@ public class ContentResultMatchers {
return result -> {
String actual = result.getResponse().getContentType();
assertTrue("Content type not set", actual != null);
MediaType actualContentType = MediaType.parseMediaType(actual);
assertTrue("Content type [" + actual + "] is not compatible with [" + contentType + "]",
actualContentType.isCompatibleWith(contentType));
if (actual != null) {
MediaType actualContentType = MediaType.parseMediaType(actual);
assertTrue("Content type [" + actual + "] is not compatible with [" + contentType + "]",
actualContentType.isCompatibleWith(contentType));
}
};
}

View File

@@ -20,6 +20,7 @@ import javax.servlet.http.Cookie;
import org.hamcrest.Matcher;
import org.springframework.test.util.AssertionErrors;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
@@ -206,7 +207,9 @@ public class CookieResultMatchers {
private static Cookie getCookie(MvcResult result, String name) {
Cookie cookie = result.getResponse().getCookie(name);
assertTrue("No cookie with name '" + name + "'", cookie != null);
if (cookie == null) {
AssertionErrors.fail("No cookie with name '" + name + "'");
}
return cookie;
}

View File

@@ -64,11 +64,13 @@ public class HandlerResultMatchers {
return result -> {
Object handler = result.getHandler();
assertTrue("No handler", handler != null);
Class<?> actual = handler.getClass();
if (HandlerMethod.class.isInstance(handler)) {
actual = ((HandlerMethod) handler).getBeanType();
if (handler != null) {
Class<?> actual = handler.getClass();
if (HandlerMethod.class.isInstance(handler)) {
actual = ((HandlerMethod) handler).getBeanType();
}
assertEquals("Handler type", type, ClassUtils.getUserClass(actual));
}
assertEquals("Handler type", type, ClassUtils.getUserClass(actual));
};
}
@@ -145,7 +147,9 @@ public class HandlerResultMatchers {
private static HandlerMethod getHandlerMethod(MvcResult result) {
Object handler = result.getHandler();
assertTrue("No handler", handler != null);
assertTrue("Not a HandlerMethod: " + handler, handler instanceof HandlerMethod);
if (!(handler instanceof HandlerMethod)) {
fail("Not a HandlerMethod: " + handler);
}
return (HandlerMethod) handler;
}

View File

@@ -109,7 +109,10 @@ public class HeaderResultMatchers {
return result -> {
MockHttpServletResponse response = result.getResponse();
assertTrue("Response does not contain header '" + name + "'", response.containsHeader(name));
assertEquals("Response header '" + name + "'", value, Long.parseLong(response.getHeader(name)));
String headerValue = response.getHeader(name);
if (headerValue != null) {
assertEquals("Response header '" + name + "'", value, Long.parseLong(headerValue));
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -24,6 +24,7 @@ import java.io.Writer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.util.CollectionUtils;
@@ -104,7 +105,7 @@ public abstract class MockMvcResultHandlers {
writer.println(String.format("%s:", heading));
}
@Override
public void printValue(String label, Object value) {
public void printValue(String label, @Nullable Object value) {
if (value != null && value.getClass().isArray()) {
value = CollectionUtils.arrayToList(value);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -102,8 +102,9 @@ public abstract class MockMvcResultMatchers {
public static ResultMatcher forwardedUrlPattern(String urlPattern) {
return result -> {
assertTrue("AntPath pattern", pathMatcher.isPattern(urlPattern));
String url = result.getResponse().getForwardedUrl();
assertTrue("Forwarded URL does not match the expected URL pattern",
pathMatcher.match(urlPattern, result.getResponse().getForwardedUrl()));
(url != null && pathMatcher.match(urlPattern, url)));
};
}
@@ -129,9 +130,10 @@ public abstract class MockMvcResultMatchers {
*/
public static ResultMatcher redirectedUrlPattern(String urlPattern) {
return result -> {
assertTrue("AntPath pattern", pathMatcher.isPattern(urlPattern));
assertTrue("No Ant-style path pattern", pathMatcher.isPattern(urlPattern));
String url = result.getResponse().getRedirectedUrl();
assertTrue("Redirected URL does not match the expected URL pattern",
pathMatcher.match(urlPattern, result.getResponse().getRedirectedUrl()));
(url != null && pathMatcher.match(urlPattern, url)));
};
}

View File

@@ -23,6 +23,7 @@ import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.servlet.ModelAndView;
import static org.hamcrest.MatcherAssert.*;
@@ -155,10 +156,12 @@ public class ModelResultMatchers {
ModelAndView mav = getModelAndView(mvcResult);
BindingResult result = getBindingResult(mav, name);
assertTrue("No errors for attribute '" + name + "'", result.hasErrors());
boolean hasFieldErrors = result.hasFieldErrors(fieldName);
assertTrue("No errors for field '" + fieldName + "' of attribute '" + name + "'", hasFieldErrors);
String code = result.getFieldError(fieldName).getCode();
assertTrue("Expected error code '" + error + "' but got '" + code + "'", code.equals(error));
FieldError fieldError = result.getFieldError(fieldName);
if (fieldError == null) {
fail("No errors for field '" + fieldName + "' of attribute '" + name + "'");
}
String code = fieldError.getCode();
assertTrue("Expected error code '" + error + "' but got '" + code + "'", error.equals(code));
};
}
@@ -173,9 +176,11 @@ public class ModelResultMatchers {
ModelAndView mav = getModelAndView(mvcResult);
BindingResult result = getBindingResult(mav, name);
assertTrue("No errors for attribute: [" + name + "]", result.hasErrors());
boolean hasFieldErrors = result.hasFieldErrors(fieldName);
assertTrue("No errors for field '" + fieldName + "' of attribute '" + name + "'", hasFieldErrors);
String code = result.getFieldError(fieldName).getCode();
FieldError fieldError = result.getFieldError(fieldName);
if (fieldError == null) {
fail("No errors for field '" + fieldName + "' of attribute '" + name + "'");
}
String code = fieldError.getCode();
assertThat("Field name '" + fieldName + "' of attribute '" + name + "'", code, matcher);
};
}
@@ -232,13 +237,17 @@ public class ModelResultMatchers {
private ModelAndView getModelAndView(MvcResult mvcResult) {
ModelAndView mav = mvcResult.getModelAndView();
assertTrue("No ModelAndView found", mav != null);
if (mav == null) {
fail("No ModelAndView found");
};
return mav;
}
private BindingResult getBindingResult(ModelAndView mav, String name) {
BindingResult result = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);
assertTrue("No BindingResult for attribute: " + name, result != null);
if (result == null) {
fail("No BindingResult for attribute: " + name);
}
return result;
}

View File

@@ -26,6 +26,7 @@ import javax.servlet.http.HttpSession;
import org.springframework.core.style.ToStringCreator;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MvcResult;
@@ -168,7 +169,7 @@ public class PrintingResultHandler implements ResultHandler {
/**
* Print the handler.
*/
protected void printHandler(Object handler, HandlerInterceptor[] interceptors) throws Exception {
protected void printHandler(@Nullable Object handler, @Nullable HandlerInterceptor[] interceptors) throws Exception {
if (handler == null) {
this.printer.printValue("Type", null);
}
@@ -187,7 +188,7 @@ public class PrintingResultHandler implements ResultHandler {
/**
* Print exceptions resolved through a HandlerExceptionResolver.
*/
protected void printResolvedException(Exception resolvedException) throws Exception {
protected void printResolvedException(@Nullable Exception resolvedException) throws Exception {
if (resolvedException == null) {
this.printer.printValue("Type", null);
}
@@ -199,7 +200,7 @@ public class PrintingResultHandler implements ResultHandler {
/**
* Print the ModelAndView.
*/
protected void printModelAndView(ModelAndView mav) throws Exception {
protected void printModelAndView(@Nullable ModelAndView mav) throws Exception {
this.printer.printValue("View name", (mav != null) ? mav.getViewName() : null);
this.printer.printValue("View", (mav != null) ? mav.getView() : null);
if (mav == null || mav.getModel().size() == 0) {
@@ -292,7 +293,7 @@ public class PrintingResultHandler implements ResultHandler {
void printHeading(String heading);
void printValue(String label, Object value);
void printValue(String label, @Nullable Object value);
}
}

View File

@@ -18,11 +18,13 @@ package org.springframework.test.web.servlet.result;
import java.util.concurrent.Callable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.hamcrest.Matcher;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.util.Assert;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;
@@ -129,7 +131,9 @@ public class RequestResultMatchers {
@SuppressWarnings("unchecked")
public <T> ResultMatcher sessionAttribute(final String name, final Matcher<T> matcher) {
return result -> {
T value = (T) result.getRequest().getSession().getAttribute(name);
HttpSession session = result.getRequest().getSession();
Assert.state(session != null, "No HttpSession");
T value = (T) session.getAttribute(name);
assertThat("Session attribute '" + name + "'", value, matcher);
};
}
@@ -139,8 +143,11 @@ public class RequestResultMatchers {
*/
@SuppressWarnings("unchecked")
public <T> ResultMatcher sessionAttribute(final String name, final Object value) {
return result ->
assertEquals("Session attribute '" + name + "'", value, result.getRequest().getSession().getAttribute(name));
return result -> {
HttpSession session = result.getRequest().getSession();
Assert.state(session != null, "No HttpSession");
assertEquals("Session attribute '" + name + "'", value, session.getAttribute(name));
};
}
private static void assertAsyncStarted(HttpServletRequest request) {

View File

@@ -49,7 +49,9 @@ public class ViewResultMatchers {
public ResultMatcher name(final Matcher<? super String> matcher) {
return result -> {
ModelAndView mav = result.getModelAndView();
assertTrue("No ModelAndView found", mav != null);
if (mav == null) {
fail("No ModelAndView found");
}
assertThat("View name", mav.getViewName(), matcher);
};
}
@@ -60,7 +62,9 @@ public class ViewResultMatchers {
public ResultMatcher name(final String expectedViewName) {
return result -> {
ModelAndView mav = result.getModelAndView();
assertTrue("No ModelAndView found", mav != null);
if (mav == null) {
fail("No ModelAndView found");
}
assertEquals("View name", expectedViewName, mav.getViewName());
};
}

View File

@@ -17,7 +17,6 @@
package org.springframework.test.web.servlet.result;
import java.util.Map;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher;
@@ -72,8 +71,9 @@ public class XpathResultMatchers {
/**
* Get the response encoding if explicitly defined in the response, {code null} otherwise.
*/
@Nullable
private String getDefinedEncoding(MockHttpServletResponse response) {
return response.isCharset() ? response.getCharacterEncoding() : null;
return (response.isCharset() ? response.getCharacterEncoding() : null);
}
/**

View File

@@ -40,7 +40,7 @@ import org.springframework.test.web.servlet.MockMvcBuilder;
* configuring filters, default request properties, global expectations and
* global result actions.
*
* <p>Sub-classes can use different strategies to prepare the Spring
* <p>Subclasses can use different strategies to prepare the Spring
* {@code WebApplicationContext} that will be passed to the
* {@code DispatcherServlet}.
*
@@ -126,9 +126,7 @@ public abstract class AbstractMockMvcBuilder<B extends AbstractMockMvcBuilder<B>
@Override
@SuppressWarnings("rawtypes")
public final MockMvc build() {
WebApplicationContext wac = initWebAppContext();
ServletContext servletContext = wac.getServletContext();
MockServletConfig mockServletConfig = new MockServletConfig(servletContext);

View File

@@ -29,49 +29,38 @@ import org.springframework.test.web.servlet.ResultMatcher;
* @author Rossen Stoyanchev
* @since 4.1
*/
public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>>
extends MockMvcBuilder {
public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>> extends MockMvcBuilder {
/**
* Add filters mapped to any request (i.e. "/*"). For example:
*
* <pre class="code">
* mockMvcBuilder.addFilters(springSecurityFilterChain);
* </pre>
*
* <p>is the equivalent of the following web.xml configuration:
*
* <pre class="code">
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* </pre>
*
* <p>Filters will be invoked in the order in which they are provided.
*
* @param filters the filters to add
*/
<T extends B> T addFilters(Filter... filters);
/**
* Add a filter mapped to a specific set of patterns. For example:
*
* <pre class="code">
* mockMvcBuilder.addFilters(myResourceFilter, "/resources/*");
* </pre>
*
* <p>is the equivalent of:
*
* <pre class="code">
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;myResourceFilter&lt;/filter-name&gt;
* &lt;url-pattern&gt;/resources/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* </pre>
*
* <p>Filters will be invoked in the order in which they are provided.
*
* @param filter the filter to add
* @param urlPatterns URL patterns to map to; if empty, "/*" is used by default
*/
@@ -85,10 +74,8 @@ public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder
*
* <p>Properties specified at the time of performing a request override the
* default properties defined here.
*
* @param requestBuilder a RequestBuilder; see static factory methods in
* {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders}
* .
*/
<T extends B> T defaultRequest(RequestBuilder requestBuilder);
@@ -96,7 +83,6 @@ public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder
* Define a global expectation that should <em>always</em> be applied to
* every response. For example, status code 200 (OK), content type
* {@code "application/json"}, etc.
*
* @param resultMatcher a ResultMatcher; see static factory methods in
* {@link org.springframework.test.web.servlet.result.MockMvcResultMatchers}
*/
@@ -106,7 +92,6 @@ public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder
* Define a global action that should <em>always</em> be applied to every
* response. For example, writing detailed information about the performed
* request and resulting response to {@code System.out}.
*
* @param resultHandler a ResultHandler; see static factory methods in
* {@link org.springframework.test.web.servlet.result.MockMvcResultHandlers}
*/
@@ -122,12 +107,10 @@ public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder
/**
* Add a {@code MockMvcConfigurer} that automates MockMvc setup and
* configures it for some specific purpose (e.g. security).
*
* <p>There is a built-in {@link SharedHttpSessionConfigurer} that can be
* used to re-use the HTTP session across requests. 3rd party frameworks
* like Spring Security also use this mechanism to provide configuration
* shortcuts.
*
* @see SharedHttpSessionConfigurer
*/
<T extends B> T apply(MockMvcConfigurer configurer);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* 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.
@@ -54,10 +54,11 @@ public class DefaultMockMvcBuilder extends AbstractMockMvcBuilder<DefaultMockMvc
this.webAppContext = webAppContext;
}
@Override
protected WebApplicationContext initWebAppContext() {
ServletContext servletContext = this.webAppContext.getServletContext();
Assert.state(servletContext != null, "No ServletContext");
ApplicationContext rootWac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
if (rootWac == null) {

View File

@@ -16,6 +16,7 @@
package org.springframework.test.web.servlet.setup;
import org.springframework.lang.Nullable;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.web.context.WebApplicationContext;
@@ -47,7 +48,8 @@ public interface MockMvcConfigurer {
* {@link ConfigurableMockMvcBuilder#apply}.
* @param builder the builder for the MockMvc
*/
void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder);
default void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
}
/**
* Invoked when the MockMvc instance is about to be created with the MockMvc
@@ -58,7 +60,11 @@ public interface MockMvcConfigurer {
* @return a post processor to be applied to every request performed
* through the {@code MockMvc} instance.
*/
RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder,
WebApplicationContext context);
@Nullable
default RequestPostProcessor beforeMockMvcCreated(
ConfigurableMockMvcBuilder<?> builder, WebApplicationContext context) {
return null;
}
}

View File

@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
import javax.servlet.ServletContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
@@ -32,6 +33,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockServletContext;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -190,7 +192,9 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
/**
* Add interceptors mapped to a set of path patterns.
*/
public StandaloneMockMvcBuilder addMappedInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) {
public StandaloneMockMvcBuilder addMappedInterceptors(
@Nullable String[] pathPatterns, HandlerInterceptor... interceptors) {
for (HandlerInterceptor interceptor : interceptors) {
this.mappedInterceptors.add(new MappedInterceptor(pathPatterns, interceptor));
}
@@ -351,21 +355,26 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
private void registerMvcSingletons(StubWebApplicationContext wac) {
StandaloneConfiguration config = new StandaloneConfiguration();
config.setApplicationContext(wac);
ServletContext sc = wac.getServletContext();
wac.addBeans(this.controllers);
wac.addBeans(this.controllerAdvice);
RequestMappingHandlerMapping hm = config.getHandlerMapping();
hm.setServletContext(wac.getServletContext());
if (sc != null) {
hm.setServletContext(sc);
}
hm.setApplicationContext(wac);
hm.afterPropertiesSet();
wac.addBean("requestMappingHandlerMapping", hm);
RequestMappingHandlerAdapter handlerAdapter = config.requestMappingHandlerAdapter();
handlerAdapter.setServletContext(wac.getServletContext());
handlerAdapter.setApplicationContext(wac);
handlerAdapter.afterPropertiesSet();
wac.addBean("requestMappingHandlerAdapter", handlerAdapter);
RequestMappingHandlerAdapter ha = config.requestMappingHandlerAdapter();
if (sc != null) {
ha.setServletContext(sc);
}
ha.setApplicationContext(wac);
ha.afterPropertiesSet();
wac.addBean("requestMappingHandlerAdapter", ha);
wac.addBean("handlerExceptionResolver", config.handlerExceptionResolver());