/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.test.web.server.matcher;
import static org.springframework.test.web.AssertionErrors.assertEquals;
import static org.springframework.test.web.AssertionErrors.assertTrue;
import static org.springframework.test.web.AssertionErrors.fail;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.AssertionErrors;
import org.springframework.test.web.server.MvcResultMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
/**
* Matchers for assertions on a {@link MockHttpServletResponse}.
*
*/
public abstract class MockResponseMatchers {
private static final Log logger = LogFactory.getLog(MockResponseMatchers.class);
private MockResponseMatchers() {
}
public static MvcResultMatcher status(final int status) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Status", status, response.getStatus());
}
};
}
public static MvcResultMatcher errorMessage(final String errorMessage) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Error message", errorMessage, response.getErrorMessage());
}
};
}
public static MvcResultMatcher contentType(final String contentType) {
return new MvcResultMatcher() {
public void match(MockHttpServletRequest rq, MockHttpServletResponse response, Object h, Exception e, ModelAndView mav) {
if (StringUtils.hasText(response.getContentType())) {
assertEquals("Content type", contentType, response.getContentType());
}
else {
String headerName = "Content-Type";
assertEquals("Content-Type response header", contentType, response.getHeader(headerName));
}
}
};
}
public static MvcResultMatcher responseBody(final String content) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) throws UnsupportedEncodingException {
assertEquals("Response body", content, response.getContentAsString());
}
};
}
public static MvcResultMatcher responseBodyContains(final String text) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) throws UnsupportedEncodingException {
String body = response.getContentAsString();
assertTrue("Response body <" + body + "> does not contain " + text, body.contains(text));
}
};
}
public static MvcResultMatcher responseBodyAsByteArray(final byte[] content) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Response body", content, response.getContentAsByteArray());
}
};
}
public static MvcResultMatcher forwardedUrl(final String forwardUrl) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Forwarded URL", forwardUrl, response.getForwardedUrl());
}
};
}
public static MvcResultMatcher redirectedUrl(final String redirectUrl) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Redirected URL", redirectUrl, response.getRedirectedUrl());
}
};
}
public static MvcResultMatcher headersPresent(final String...headerNames) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesPresent("Response header", getHeaderValueMap(response), headerNames);
}
};
}
public static MvcResultMatcher headersNotPresent(final String...headerNames) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesNotPresent("Response header", getHeaderValueMap(response), headerNames);
}
};
}
public static MvcResultMatcher headerValue(final String headerName, final Object headerValue) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Response header", headerValue, response.getHeader(headerName));
}
};
}
public static MvcResultMatcher headerValueContains(final String headerName, final String text) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesPresent("Response header", getHeaderValueMap(response), headerName);
Object value = response.getHeader(headerName);
assertEquals("Header value type", String.class, response.getHeader(headerName).getClass());
assertTrue("Header '" + headerName + "' with value <" + value + "> does not contain <" + text + ">.",
((String) value).contains(text));
}
};
}
public static MvcResultMatcher cookiesPresent(final String...names) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesPresent("Response cookie", getCookieValueMap(response), names);
}
};
}
public static MvcResultMatcher cookiesNotPresent(final String...names) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesNotPresent("Response cookie", getCookieValueMap(response), names);
}
};
}
public static MvcResultMatcher cookieValue(final String name, final String value) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
assertEquals("Response cookie", value, response.getCookie(name).getValue());
}
};
}
public static MvcResultMatcher cookieValueContains(final String cookieName, final String text) {
return new MockResponseResultMatcher() {
protected void matchMockResponse(MockHttpServletResponse response) {
AssertionErrors.assertNameValuesPresent("Response cookie", getCookieValueMap(response), cookieName);
String value = response.getCookie(cookieName).getValue();
assertTrue("Cookie '" + cookieName + "' with value <" + value + "> does not contain <" + text + ">.",
value.contains(text));
}
};
}
static Map<String, Object> getHeaderValueMap(MockHttpServletResponse response) {
Map<String, Object> headers = new LinkedHashMap<String, Object>();
for (String name : response.getHeaderNames()) {
headers.put(name, response.getHeader(name));
}
return headers;
}
static Map<String, Object> getCookieValueMap(MockHttpServletResponse response) {
Map<String, Object> cookies = new LinkedHashMap<String, Object>();
for (Cookie cookie : response.getCookies()) {
cookies.put(cookie.getName(), cookie.getValue());
}
return cookies;
}
private static abstract class MockResponseResultMatcher implements MvcResultMatcher {
public void match(MockHttpServletRequest request,
MockHttpServletResponse response,
Object handler,
Exception handlerException,
ModelAndView mav) {
try {
matchMockResponse(response);
} catch (IOException e) {
logger.error(e.getMessage(), e);
fail("Failed mock response expectation: " + e.getMessage());
}
}
protected abstract void matchMockResponse(MockHttpServletResponse response) throws IOException;
}
}