提交 22bcb54a 编写于 作者: R Rob Winch 提交者: Rossen Stoyanchev

Add Spring MVC Test framework

This commit adds the spring-test-mvc project [1] to the Spring
Framework as part of the spring-test module.

The sources are added as a root-level project called "spring-test-mvc"
instead of under "spring-test" because the new sources need to be
compiled with Servlet 3 while the current "spring-test" sources require
Servlet 2.5 and the Eclipse IDE does not support having different
classpaths for the same project.

The Gradle build produces a single spring-test jar that contains
sources from both "spring-test" and "spring-test-mvc". This merge is
made possible through merge-dist.gradle as follows:

- jar tasks of the "from" project execute tasks of the "to" project
- "to" project is added to the classpath of the "from" project
- "to" project pom is updated with entries from the "from" project

For further details see documentation in merge-dist.gradle.

Special thanks to everyone who contributed to the initial development
of the Spring MVC Test framework:

 Arjen Poutsma <poutsma@mac.com>
 Craig Walls <cwalls@vmware.com>
 Frans Flippo <fransflippo@utopia.orange11.nl>
 Harry Lascelles <harry@firstbanco.com>
 Irfan <mail.urfi@gmail.com>
 Jörg Rathlev <joerg.rathlev@s24.com>
 Keesun Baik <whiteship2000@gmail.com>
 Keesun Baik <whiteship@epril.com>
 Matthew Reid <matthew.reid@nakedwines.com>
 Nils-Helge Garli Hegvik <Nils-Helge.Hegvik@telenor.com>
 Rob Winch <rwinch@vmware.com>
 Scott Frederick <sfrederick@vmware.com>
 Sven Filatov <sven.filatov@gmail.com>
 Thomas Bruyelle <thomas.bruyelle@gmail.com>
 youngm <youngm@gmail.com>

[1]: https://github.com/SpringSource/spring-test-mvc

Issue: SPR-9859, SPR-7951
上级 4812c181
......@@ -548,6 +548,48 @@ project('spring-test') {
}
}
project('spring-test-mvc') {
description = 'Spring Test MVC Framework'
apply from: 'test-mvc.gradle'
dependencies {
compile project(":spring-context")
compile project(":spring-webmvc")
compile project(":spring-test").sourceSets.main.output
compile("org.apache.tomcat:tomcat-servlet-api:7.0.8", provided)
compile "org.hamcrest:hamcrest-all:1.1"
compile("com.jayway.jsonpath:json-path:0.8.1", optional)
compile("xmlunit:xmlunit:1.2", optional)
testCompile("org.slf4j:jcl-over-slf4j:1.6.1")
testCompile("org.slf4j:slf4j-log4j12:1.6.1") {
exclude group: 'log4j', module: 'log4j'
}
testCompile("log4j:log4j:1.2.15") {
exclude group: 'javax.mail', module: 'mail'
exclude group: 'javax.jms', module: 'jms'
exclude group: 'com.sun.jdmk', module: 'jmxtools'
exclude group: 'com.sun.jmx', module: 'jmxri'
}
testCompile "javax.servlet:jstl:1.2"
testCompile "org.apache.tiles:tiles-jsp:2.2.2"
testCompile "org.hibernate:hibernate-validator:4.2.0.Final"
testCompile "org.codehaus.jackson:jackson-mapper-asl:1.4.2"
testCompile project(":spring-oxm")
testCompile "com.thoughtworks.xstream:xstream:1.3.1"
testCompile "cglib:cglib-nodep:2.2"
testCompile "rome:rome:1.0"
testCompile "javax.xml.bind:jaxb-api:2.2.6"
testCompile("org.springframework.security:spring-security-core:3.1.2.RELEASE") {
exclude group: 'org.springframework'
}
testCompile("org.springframework.security:spring-security-web:3.1.2.RELEASE") {
exclude group: 'org.springframework'
}
testCompile("org.springframework.security:spring-security-config:3.1.2.RELEASE") {
exclude group: 'org.springframework'
}
}
}
project('spring-struts') {
description = 'Spring Struts'
dependencies {
......
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
/**
* Will merge the distributions of the current project into mergeIntoProject. For
* example, to bundle spring-test-mvc in spring-test's jars. This script will perform the
* following steps:
* <ul>
* <li>Ensure that jar tasks of the project being merged from will execute the tasks of
* the project being merged into</li>
* <li>Add the project being merged into to the classpath of the project being merged
* from</li>
* <li>Update the pom.xml of the project being merged into to contain the entries from
* the project being merged from</li>
* </ul>
*
* Example Usage:
*
* ext.mergeIntoProject = project(':spring-test')
* apply from: "${rootProject.projectDir}/merge-dist.gradle"
*/
def mergeFromProject = project
// invoking a task on mergeFromProject will invoke the task with the same name on mergeIntoProject
def taskNamesToMerge = ['sourcesJar','jar','javadocJar','javadoc','install']
taskNamesToMerge.each { taskName ->
def taskToRemove = tasks.getByPath(taskName)
taskToRemove.enabled = false
taskToRemove.dependsOn mergeIntoProject."$taskName"
}
// update mergeIntoProject artifacts to contain the mergeFromProject artifact contents
mergeIntoProject."sourcesJar" {
from mergeFromProject.sourcesJar.source
}
mergeIntoProject."jar" {
from mergeFromProject.jar.source
}
mergeIntoProject."javadoc" {
source += mergeFromProject.javadoc.source
classpath += mergeFromProject.javadoc.classpath
}
// GRADLE-1116
mergeFromProject.eclipse.classpath.file.whenMerged { classpath ->
classpath.entries.removeAll { entry -> entry.path.contains("/${mergeIntoProject.name}/build/") }
def dependency = new ProjectDependency("/${mergeIntoProject.name}", mergeIntoProject.path)
dependency.exported = true
classpath.entries.add(dependency)
}
// Update mergeIntoProject to contain additional configurations that contains all the dependencies from mergeFromProject
// so that Maven pom generation works
gradle.taskGraph.whenReady {
mergeFromProject.configurations.archives.artifacts.clear()
mergeFromProject.configurations.each { config->
def mapping = mergeFromProject.conf2ScopeMappings.getMapping([config])
if(mapping.scope) {
def newConfigName = mergeFromProject.name + "-"+ config.name
mergeIntoProject.configurations.add(newConfigName)
config.dependencies.each { dependency ->
mergeIntoProject.dependencies.add(newConfigName, dependency)
}
configure(mergeIntoProject.install.repositories.mavenInstaller.pom.scopeMappings) {
addMapping(mapping.priority + 100, mergeIntoProject.configurations."$newConfigName", mapping.scope)
}
mergeIntoProject.optionalDeps += mergeFromProject.optionalDeps
mergeIntoProject.providedDeps += mergeFromProject.providedDeps
}
}
}
......@@ -15,6 +15,7 @@ include 'spring-orm'
include 'spring-oxm'
include 'spring-struts'
include 'spring-test'
include 'spring-test-mvc'
include 'spring-tx'
include 'spring-web'
include 'spring-webmvc'
......
/*
* Copyright 2002-2012 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.mock;
/**
* JUnit independent assertion class.
*
* @author Lukas Krecan
* @author Arjen Poutsma
* @since 3.2
*/
public abstract class AssertionErrors {
private AssertionErrors() {
}
/**
* Fails a test with the given message.
*
* @param message the message
*/
public static void fail(String message) {
throw new AssertionError(message);
}
/**
* Fails a test with the given message passing along expected and actual values to be added to the message.
*
* @param message the message
* @param expected the expected value
* @param actual the actual value
*/
public static void fail(String message, Object expected, Object actual) {
throw new AssertionError(message + " expected:<" + expected + "> but was:<" + actual + ">");
}
/**
* Asserts that a condition is {@code true}. If not, throws an {@link AssertionError} with the given message.
*
* @param message the message
* @param condition the condition to test for
*/
public static void assertTrue(String message, boolean condition) {
if (!condition) {
fail(message);
}
}
/**
* Asserts that two objects are equal. If not, an {@link AssertionError} is thrown with the given message.
*
* @param message the message
* @param expected the expected value
* @param actual the actual value
*/
public static void assertEquals(String message, Object expected, Object actual) {
if (expected == null && actual == null) {
return;
}
if (expected != null && expected.equals(actual)) {
return;
}
fail(message, expected, actual);
}
}
/*
* Copyright 2002-2012 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.mock.client;
import java.io.IOException;
import java.net.URI;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.test.web.mock.client.match.RequestMatchers;
import org.springframework.test.web.mock.client.response.ResponseCreators;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.support.RestGatewaySupport;
/**
* <strong>Main entry point for client-side REST testing</strong>. Used for tests
* that involve direct or indirect (through client code) use of the
* {@link RestTemplate}. Provides a way to set up fine-grained expectations
* on the requests that will be performed through the {@code RestTemplate} and
* a way to define the responses to send back removing the need for an
* actual running server.
*
* <p>Below is an example:
* <pre>
* RestTemplate restTemplate = new RestTemplate()
* MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
*
* mockServer.expect(requestTo("/hotels/42")).andExpect(method(HttpMethod.GET))
* .andRespond(withSuccess("{ \"id\" : \"42\", \"name\" : \"Holiday Inn\"}", MediaType.APPLICATION_JSON));
*
* Hotel hotel = restTemplate.getForObject("/hotels/{id}", Hotel.class, 42);
* &#47;&#47; Use the hotel instance...
*
* mockServer.verify();
*
* <p>To create an instance of this class, use {@link #createServer(RestTemplate)}
* and provide the {@code RestTemplate} to set up for the mock testing.
*
* <p>After that use {@link #expect(RequestMatcher)} and fluent API methods
* {@link ResponseActions#andExpect(RequestMatcher) andExpect(RequestMatcher)} and
* {@link ResponseActions#andRespond(ResponseCreator) andRespond(ResponseCreator)}
* to set up request expectations and responses, most likely relying on the default
* {@code RequestMatcher} implementations provided in {@link RequestMatchers}
* and the {@code ResponseCreator} implementations provided in
* {@link ResponseCreators} both of which can be statically imported.
*
* <p>At the end of the test use {@link #verify()} to ensure all expected
* requests were actually performed.
*
* <p>Note that because of the fluent API offered by this class (and related
* classes), you can typically use the Code Completion features (i.e.
* ctrl-space) in your IDE to set up the mocks.
*
* <p><strong>Credits:</strong> The client-side REST testing support was
* inspired by and initially based on similar code in the Spring WS project for
* client-side tests involving the {@code WebServiceTemplate}.
*
* @author Craig Walls
* @author Rossen Stoyanchev
* @since 3.2
*/
public class MockRestServiceServer {
private final List<RequestMatcherClientHttpRequest> expectedRequests =
new LinkedList<RequestMatcherClientHttpRequest>();
private final List<RequestMatcherClientHttpRequest> actualRequests =
new LinkedList<RequestMatcherClientHttpRequest>();
/**
* Private constructor.
* @see #createServer(RestTemplate)
* @see #createServer(RestGatewaySupport)
*/
private MockRestServiceServer() {
}
/**
* Create a {@code MockRestServiceServer} and set up the given
* {@code RestTemplate} with a mock {@link ClientHttpRequestFactory}.
*
* @param restTemplate the RestTemplate to set up for mock testing
* @return the created mock server
*/
public static MockRestServiceServer createServer(RestTemplate restTemplate) {
Assert.notNull(restTemplate, "'restTemplate' must not be null");
MockRestServiceServer mockServer = new MockRestServiceServer();
RequestMatcherClientHttpRequestFactory factory = mockServer.new RequestMatcherClientHttpRequestFactory();
restTemplate.setRequestFactory(factory);
return mockServer;
}
/**
* Create a {@code MockRestServiceServer} and set up the given
* {@code RestGatewaySupport} with a mock {@link ClientHttpRequestFactory}.
*
* @param restGateway the REST gateway to set up for mock testing
* @return the created mock server
*/
public static MockRestServiceServer createServer(RestGatewaySupport restGateway) {
Assert.notNull(restGateway, "'gatewaySupport' must not be null");
return createServer(restGateway.getRestTemplate());
}
/**
* Set up a new HTTP request expectation. The returned {@link ResponseActions}
* is used to set up further expectations and to define the response.
*
* <p>This method may be invoked multiple times before starting the test, i.e.
* before using the {@code RestTemplate}, to set up expectations for multiple
* requests.
*
* @param requestMatcher a request expectation, see {@link RequestMatchers}
* @return used to set up further expectations or to define a response
*/
public ResponseActions expect(RequestMatcher requestMatcher) {
Assert.state(this.actualRequests.isEmpty(), "Can't add more expected requests with test already underway");
RequestMatcherClientHttpRequest request = new RequestMatcherClientHttpRequest(requestMatcher);
this.expectedRequests.add(request);
return request;
}
/**
* Verify that all expected requests set up via
* {@link #expect(RequestMatcher)} were indeed performed.
*
* @throws AssertionError when some expectations were not met
*/
public void verify() {
if (this.expectedRequests.isEmpty() || this.expectedRequests.equals(this.actualRequests)) {
return;
}
throw new AssertionError(getVerifyMessage());
}
private String getVerifyMessage() {
StringBuilder sb = new StringBuilder("Further request(s) expected\n");
if (this.actualRequests.size() > 0) {
sb.append("The following ");
}
sb.append(this.actualRequests.size()).append(" out of ");
sb.append(this.expectedRequests.size()).append(" were executed");
if (this.actualRequests.size() > 0) {
sb.append(":\n");
for (RequestMatcherClientHttpRequest request : this.actualRequests) {
sb.append(request.toString()).append("\n");
}
}
return sb.toString();
}
/**
* Mock ClientHttpRequestFactory that creates requests by iterating
* over the list of expected {@link RequestMatcherClientHttpRequest}'s.
*/
private class RequestMatcherClientHttpRequestFactory implements ClientHttpRequestFactory {
private Iterator<RequestMatcherClientHttpRequest> requestIterator;
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
Assert.notNull(uri, "'uri' must not be null");
Assert.notNull(httpMethod, "'httpMethod' must not be null");
if (this.requestIterator == null) {
this.requestIterator = MockRestServiceServer.this.expectedRequests.iterator();
}
if (!this.requestIterator.hasNext()) {
throw new AssertionError("No further requests expected");
}
RequestMatcherClientHttpRequest request = this.requestIterator.next();
request.setURI(uri);
request.setMethod(httpMethod);
MockRestServiceServer.this.actualRequests.add(request);
return request;
}
}
}
/*
* Copyright 2002-2012 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.mock.client;
import java.io.IOException;
import org.springframework.http.client.ClientHttpRequest;
/**
* A contract for matching requests to expectations.
*
* @author Craig Walls
* @since 3.2
*/
public interface RequestMatcher {
/**
* Match the given request against some expectations.
*
* @param request the request to make assertions on
* @throws IOException in case of I/O errors
* @throws AssertionError if expectations are not met
*/
void match(ClientHttpRequest request) throws IOException, AssertionError;
}
/*
* Copyright 2002-2012 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.mock.client;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.util.Assert;
/**
* A specialization of {@code MockClientHttpRequest} that matches the request
* against a set of expectations, via {@link RequestMatcher} instances. The
* expectations are checked when the request is executed. This class also uses a
* {@link ResponseCreator} to create the response.
*
* @author Craig Walls
* @author Rossen Stoyanchev
* @since 3.2
*/
class RequestMatcherClientHttpRequest extends MockClientHttpRequest implements ResponseActions {
private final List<RequestMatcher> requestMatchers = new LinkedList<RequestMatcher>();
private ResponseCreator responseCreator;
public RequestMatcherClientHttpRequest(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "RequestMatcher is required");
this.requestMatchers.add(requestMatcher);
}
public ResponseActions andExpect(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "RequestMatcher is required");
this.requestMatchers.add(requestMatcher);
return this;
}
public void andRespond(ResponseCreator responseCreator) {
Assert.notNull(responseCreator, "ResponseCreator is required");
this.responseCreator = responseCreator;
}
public ClientHttpResponse execute() throws IOException {
if (this.requestMatchers.isEmpty()) {
throw new AssertionError("No request expectations to execute");
}
if (this.responseCreator == null) {
throw new AssertionError("No ResponseCreator was set up. Add it after request expectations, "
+ "e.g. MockRestServiceServer.expect(requestTo(\"/foo\")).andRespond(withSuccess())");
}
for (RequestMatcher requestMatcher : this.requestMatchers) {
requestMatcher.match(this);
}
setResponse(this.responseCreator.createResponse(this));
return super.execute();
}
}
/*
* Copyright 2002-2012 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.mock.client;
/**
* A contract for setting up request expectations and defining a response.
* Implementations can be obtained through {@link MockRestServiceServer#expect(RequestMatcher)}.
*
* @author Craig Walls
* @since 3.2
*/
public interface ResponseActions {
/**
* Add a request expectation.
* @return the expectation
*/
ResponseActions andExpect(RequestMatcher requestMatcher);
/**
* Define the response.
* @param responseCreator the creator of the response
*/
void andRespond(ResponseCreator responseCreator);
}
/*
* Copyright 2002-2012 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.mock.client;
import java.io.IOException;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.web.mock.client.response.ResponseCreators;
/**
* A contract for creating a {@link ClientHttpResponse}.
* Implementations can be obtained via {@link ResponseCreators}.
*
* @author Craig Walls
* @since 3.2
*/
public interface ResponseCreator {
/**
* Create a response for the given request.
* @param request the request
*/
ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException;
}
/*
* Copyright 2002-2012 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.mock.client.match;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
import java.io.IOException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.client.RequestMatcher;
import org.springframework.test.web.mock.support.XmlExpectationsHelper;
import org.w3c.dom.Node;
/**
* Factory for request content {@code RequestMatcher}'s. An instance of this
* class is typically accessed via {@link RequestMatchers#content()}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class ContentRequestMatchers {
private final XmlExpectationsHelper xmlHelper;
/**
* Class constructor, not for direct instantiation.
* Use {@link RequestMatchers#content()}.
*/
protected ContentRequestMatchers() {
this.xmlHelper = new XmlExpectationsHelper();
}
/**
* Assert the request content type as a String.
*/
public RequestMatcher mimeType(String expectedContentType) {
return mimeType(MediaType.parseMediaType(expectedContentType));
}
/**
* Assert the request content type as a {@link MediaType}.
*/
public RequestMatcher mimeType(final MediaType expectedContentType) {
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
MediaType actualContentType = request.getHeaders().getContentType();
assertTrue("Content type not set", actualContentType != null);
assertEquals("Content type", expectedContentType, actualContentType);
}
};
}
/**
* Get the body of the request as a UTF-8 string and appply the given {@link Matcher}.
*/
public RequestMatcher string(final Matcher<? super String> matcher) {
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
MatcherAssert.assertThat("Request content", mockRequest.getBodyAsString(), matcher);
}
};
}
/**
* Get the body of the request as a UTF-8 string and compare it to the given String.
*/
public RequestMatcher string(String expectedContent) {
return string(Matchers.equalTo(expectedContent));
}
/**
* Compare the body of the request to the given byte array.
*/
public RequestMatcher bytes(final byte[] expectedContent) {
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
byte[] content = mockRequest.getBodyAsBytes();
MatcherAssert.assertThat("Request content", content, Matchers.equalTo(expectedContent));
}
};
}
/**
* Parse the request body and the given String as XML and assert that the
* two are "similar" - i.e. they contain the same elements and attributes
* regardless of order.
*
* <p>Use of this matcher assumes the
* <a href="http://xmlunit.sourceforge.net/">XMLUnit<a/> library is available.
*
* @param expectedXmlContent the expected XML content
*/
public RequestMatcher xml(final String expectedXmlContent) {
return new AbstractXmlRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xmlHelper.assertXmlEqual(expectedXmlContent, request.getBodyAsString());
}
};
}
/**
* Parse the request content as {@link Node} and apply the given {@link Matcher}.
*/
public RequestMatcher node(final Matcher<? super Node> matcher) {
return new AbstractXmlRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xmlHelper.assertNode(request.getBodyAsString(), matcher);
}
};
}
/**
* Parse the request content as {@link DOMSource} and apply the given {@link Matcher}.
* @see <a href="http://code.google.com/p/xml-matchers/">http://code.google.com/p/xml-matchers/</a>
*/
public RequestMatcher source(final Matcher<? super Source> matcher) {
return new AbstractXmlRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xmlHelper.assertSource(request.getBodyAsString(), matcher);
}
};
}
/**
* Abstract base class for XML {@link RequestMatcher}'s.
*/
private abstract static class AbstractXmlRequestMatcher implements RequestMatcher {
public final void match(ClientHttpRequest request) throws IOException, AssertionError {
try {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
matchInternal(mockRequest);
}
catch (Exception e) {
throw new AssertionError("Failed to parse expected or actual XML request content: " + e.getMessage());
}
}
protected abstract void matchInternal(MockClientHttpRequest request) throws Exception;
}
}
/*
* Copyright 2002-2012 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.mock.client.match;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import org.hamcrest.Matcher;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.client.RequestMatcher;
import org.springframework.test.web.mock.support.JsonPathExpectationsHelper;
/**
* Factory methods for request content {@code RequestMatcher}'s using a <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expression.
* An instance of this class is typically accessed via
* {@code RequestMatchers.jsonPath(..)}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class JsonPathRequestMatchers {
private JsonPathExpectationsHelper jsonPathHelper;
/**
* Class constructor, not for direct instantiation. Use
* {@link RequestMatchers#jsonPath(String, Matcher)} or
* {@link RequestMatchers#jsonPath(String, Object...)}.
*
* @param expression the JSONPath expression
* @param args arguments to parameterize the JSONPath expression with using
* the formatting specifiers defined in
* {@link String#format(String, Object...)}
*/
protected JsonPathRequestMatchers(String expression, Object ... args) {
this.jsonPathHelper = new JsonPathExpectationsHelper(expression, args);
}
/**
* Evaluate the JSONPath and assert the resulting value with the given {@code Matcher}.
*/
public <T> RequestMatcher value(final Matcher<T> matcher) {
return new AbstractJsonPathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
jsonPathHelper.assertValue(request.getBodyAsString(), matcher);
}
};
}
/**
* Apply the JSONPath and assert the resulting value.
*/
public RequestMatcher value(Object expectedValue) {
return value(equalTo(expectedValue));
}
/**
* Apply the JSONPath and assert the resulting value.
*/
public RequestMatcher exists() {
return new AbstractJsonPathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
jsonPathHelper.exists(request.getBodyAsString());
}
};
}
/**
* Evaluate the JSON path and assert the resulting content exists.
*/
public RequestMatcher doesNotExist() {
return new AbstractJsonPathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
jsonPathHelper.doesNotExist(request.getBodyAsString());
}
};
}
/**
* Assert the content at the given JSONPath is an array.
*/
public RequestMatcher isArray() {
return value(instanceOf(List.class));
}
/**
* Abstract base class for JSONPath {@link RequestMatcher}'s.
*/
private abstract static class AbstractJsonPathRequestMatcher implements RequestMatcher {
public final void match(ClientHttpRequest request) throws IOException, AssertionError {
try {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
matchInternal(mockRequest);
}
catch (ParseException e) {
throw new AssertionError("Failed to parse JSON request content: " + e.getMessage());
}
}
protected abstract void matchInternal(MockClientHttpRequest request) throws IOException, ParseException;
}
}
/*
* Copyright 2002-2012 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.mock.client.match;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.core.IsEqual;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.AssertionErrors;
import org.springframework.test.web.mock.client.MockRestServiceServer;
import org.springframework.test.web.mock.client.RequestMatcher;
import org.springframework.util.Assert;
/**
* Static, factory methods for {@link RequestMatcher} classes. Typically used to
* provide input for {@link MockRestServiceServer#expect(RequestMatcher)}.
*
* <p><strong>Eclipse users:</strong> consider adding this class as a Java editor
* favorite. To navigate, open the Preferences and type "favorites".
*
* @author Craig Walls
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class RequestMatchers {
/**
* Private class constructor.
*/
private RequestMatchers() {
}
/**
* Match to any request.
*/
public static RequestMatcher anything() {
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws AssertionError {
}
};
}
/**
* Assert the request URI string with the given matcher.
*
* @param matcher String matcher for the expected URI
* @return the request matcher
*/
public static RequestMatcher requestTo(final Matcher<String> matcher) {
Assert.notNull(matcher, "'matcher' must not be null");
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
MatcherAssert.assertThat("Request URI", request.getURI().toString(), matcher);
}
};
}
/**
* Assert the request URI string.
*
* @param uri the expected URI
* @return the request matcher
*/
public static RequestMatcher requestTo(String uri) {
Assert.notNull(uri, "'uri' must not be null");
return requestTo(Matchers.equalTo(uri));
}
/**
* Assert the {@link HttpMethod} of the request.
*
* @param method the HTTP method
* @return the request matcher
*/
public static RequestMatcher method(final HttpMethod method) {
Assert.notNull(method, "'method' must not be null");
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws AssertionError {
AssertionErrors.assertEquals("Unexpected HttpMethod", method, request.getMethod());
}
};
}
/**
* Expect a request to the given URI.
*
* @param uri the expected URI
* @return the request matcher
*/
public static RequestMatcher requestTo(final URI uri) {
Assert.notNull(uri, "'uri' must not be null");
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws IOException, AssertionError {
AssertionErrors.assertEquals("Unexpected request", uri, request.getURI());
}
};
}
/**
* Assert request header values with the given Hamcrest matcher.
*/
public static RequestMatcher header(final String name, final Matcher<? super String>... matchers) {
return new RequestMatcher() {
public void match(ClientHttpRequest request) {
HttpHeaders headers = request.getHeaders();
List<String> values = headers.get(name);
AssertionErrors.assertTrue("Expected header <" + name + ">", values != null);
AssertionErrors.assertTrue("Expected header <" + name + "> to have at least <" + matchers.length
+ "> values but it has only <" + values.size() + ">", matchers.length <= values.size());
for (int i = 0 ; i < matchers.length; i++) {
MatcherAssert.assertThat("Request header", headers.get(name).get(i), matchers[i]);
}
}
};
}
/**
* Assert request header values.
*/
public static RequestMatcher header(String name, String... values) {
@SuppressWarnings("unchecked")
Matcher<? super String>[] matchers = new IsEqual[values.length];
for (int i = 0; i < values.length; i++) {
matchers[i] = Matchers.equalTo(values[i]);
}
return header(name, matchers);
}
/**
* Access to request body matchers.
*/
public static ContentRequestMatchers content() {
return new ContentRequestMatchers();
}
/**
* Access to request body matchers using a <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expression to
* inspect a specific subset of the body. The JSON path expression can be a
* parameterized string using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the JSON path optionally parameterized with arguments
* @param args arguments to parameterize the JSON path expression with
*/
public static JsonPathRequestMatchers jsonPath(String expression, Object ... args) {
return new JsonPathRequestMatchers(expression, args);
}
/**
* Access to request body matchers using a <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expression to
* inspect a specific subset of the body and a Hamcrest match for asserting
* the value found at the JSON path.
*
* @param expression the JSON path expression
* @param matcher a matcher for the value expected at the JSON path
*/
public static <T> RequestMatcher jsonPath(String expression, Matcher<T> matcher) {
return new JsonPathRequestMatchers(expression).value(matcher);
}
/**
* Access to request body matchers using an XPath to inspect a specific
* subset of the body. The XPath expression can be a parameterized string
* using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the XPath optionally parameterized with arguments
* @param args arguments to parameterize the XPath expression with
*/
public static XpathRequestMatchers xpath(String expression, Object... args) throws XPathExpressionException {
return new XpathRequestMatchers(expression, null, args);
}
/**
* Access to response body matchers using an XPath to inspect a specific
* subset of the body. The XPath expression can be a parameterized string
* using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the XPath optionally parameterized with arguments
* @param namespaces namespaces referenced in the XPath expression
* @param args arguments to parameterize the XPath expression with
*/
public static XpathRequestMatchers xpath(String expression, Map<String, String> namespaces, Object... args)
throws XPathExpressionException {
return new XpathRequestMatchers(expression, namespaces, args);
}
// Deprecated methods ..
/**
* Expect that the specified request header contains a subtring
*
* @deprecated in favor of {@link #header(String, Matcher...)}
*/
public static RequestMatcher headerContains(final String header, final String substring) {
Assert.notNull(header, "'header' must not be null");
Assert.notNull(substring, "'substring' must not be null");
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws AssertionError {
List<String> actualHeaders = request.getHeaders().get(header);
AssertionErrors.assertTrue("Expected header <" + header + "> in request", actualHeaders != null);
boolean foundMatch = false;
for (String headerValue : actualHeaders) {
if (headerValue.contains(substring)) {
foundMatch = true;
break;
}
}
AssertionErrors.assertTrue("Expected value containing <" + substring + "> in header <" + header + ">",
foundMatch);
}
};
}
/**
* Expect the given request body content.
*
* @deprecated in favor of {@link #content()} as well as {@code jsonPath(..)},
* and {@code xpath(..)} methods in this class
*/
public static RequestMatcher body(final String body) {
Assert.notNull(body, "'body' must not be null");
return new RequestMatcher() {
public void match(ClientHttpRequest request) throws AssertionError, IOException {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
AssertionErrors.assertEquals("Unexpected body content", body, mockRequest.getBodyAsString());
}
};
}
}
/*
* Copyright 2002-2012 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.mock.client.match;
import java.io.IOException;
import java.util.Map;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.mock.client.RequestMatcher;
import org.springframework.test.web.mock.support.XpathExpectationsHelper;
import org.w3c.dom.Node;
/**
* Factory methods for request content {@code RequestMatcher}'s using an XPath
* expression. An instance of this class is typically accessed via
* {@code RequestMatchers.xpath(..)}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class XpathRequestMatchers {
private final XpathExpectationsHelper xpathHelper;
/**
* Class constructor, not for direct instantiation. Use
* {@link RequestMatchers#xpath(String, Object...)} or
* {@link RequestMatchers#xpath(String, Map, Object...)}.
*
* @param expression the XPath expression
* @param namespaces XML namespaces referenced in the XPath expression, or {@code null}
* @param args arguments to parameterize the XPath expression with using the
* formatting specifiers defined in {@link String#format(String, Object...)}
*
* @throws XPathExpressionException
*/
protected XpathRequestMatchers(String expression, Map<String, String> namespaces, Object ... args)
throws XPathExpressionException {
this.xpathHelper = new XpathExpectationsHelper(expression, namespaces, args);
}
/**
* Apply the XPath and assert it with the given {@code Matcher<Node>}.
*/
public <T> RequestMatcher node(final Matcher<? super Node> matcher) {
return new AbstractXpathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xpathHelper.assertNode(request.getBodyAsString(), matcher);
}
};
}
/**
* Assert that content exists at the given XPath.
*/
public <T> RequestMatcher exists() {
return node(Matchers.notNullValue());
}
/**
* Assert that content does not exist at the given XPath.
*/
public <T> RequestMatcher doesNotExist() {
return node(Matchers.nullValue());
}
/**
* Apply the XPath and assert the number of nodes found with the given
* {@code Matcher<Integer>}.
*/
public <T> RequestMatcher nodeCount(final Matcher<Integer> matcher) {
return new AbstractXpathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xpathHelper.assertNodeCount(request.getBodyAsString(), matcher);
}
};
}
/**
* Apply the XPath and assert the number of nodes found.
*/
public <T> RequestMatcher nodeCount(int expectedCount) {
return nodeCount(Matchers.equalTo(expectedCount));
}
/**
* Apply the XPath and assert the String content found with the given matcher.
*/
public <T> RequestMatcher string(final Matcher<? super String> matcher) {
return new AbstractXpathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xpathHelper.assertString(request.getBodyAsString(), matcher);
}
};
}
/**
* Apply the XPath and assert the String content found.
*/
public RequestMatcher string(String value) {
return string(Matchers.equalTo(value));
}
/**
* Apply the XPath and assert the number found with the given matcher.
*/
public <T> RequestMatcher number(final Matcher<? super Double> matcher) {
return new AbstractXpathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xpathHelper.assertNumber(request.getBodyAsString(), matcher);
}
};
}
/**
* Apply the XPath and assert the number of nodes found.
*/
public RequestMatcher number(Double value) {
return number(Matchers.equalTo(value));
}
/**
* Apply the XPath and assert the boolean value found.
*/
public <T> RequestMatcher booleanValue(final Boolean value) {
return new AbstractXpathRequestMatcher() {
@Override
protected void matchInternal(MockClientHttpRequest request) throws Exception {
xpathHelper.assertBoolean(request.getBodyAsString(), value);
}
};
}
/**
* Abstract base class for XPath {@link RequestMatcher}'s.
*/
private abstract static class AbstractXpathRequestMatcher implements RequestMatcher {
public final void match(ClientHttpRequest request) throws IOException, AssertionError {
try {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;
matchInternal(mockRequest);
}
catch (Exception e) {
throw new AssertionError("Failed to parse XML request content: " + e.getMessage());
}
}
protected abstract void matchInternal(MockClientHttpRequest request) throws Exception;
}
}
/*
* Copyright 2002-2012 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.
*/
/**
* Contains built-in {@link org.springframework.test.web.mock.client.RequestMatcher}
* implementations. Use
* {@link org.springframework.test.web.mock.client.match.RequestMatchers}
* to gain access to instances of those implementations.
*/
package org.springframework.test.web.mock.client.match;
/*
* Copyright 2002-2012 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.
*/
/**
* Contains client-side REST testing support.
* @see org.springframework.test.web.mock.client.MockRestServiceServer
*/
package org.springframework.test.web.mock.client;
/*
* Copyright 2002-2012 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.mock.client.response;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.test.web.mock.client.ResponseCreator;
import org.springframework.util.Assert;
/**
* A {@code ResponseCreator} with builder-style methods for adding response details.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class DefaultResponseCreator implements ResponseCreator {
private byte[] content;
private Resource contentResource;
private final HttpHeaders headers = new HttpHeaders();
private HttpStatus statusCode;
/**
* Protected constructor.
* Use static factory methods in {@link ResponseCreators}.
*/
protected DefaultResponseCreator(HttpStatus statusCode) {
Assert.notNull(statusCode);
this.statusCode = statusCode;
}
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
MockClientHttpResponse response;
if (this.contentResource != null ){
InputStream stream = this.contentResource.getInputStream();
response = new MockClientHttpResponse(stream, this.statusCode);
}
else {
response = new MockClientHttpResponse(this.content, this.statusCode);
}
response.getHeaders().putAll(this.headers);
return response;
}
/**
* Set the body as a UTF-8 String.
*/
public DefaultResponseCreator body(String content) {
try {
this.content = content.getBytes("UTF-8");
}
catch (UnsupportedEncodingException e) {
// should not happen, UTF-8 is always supported
throw new IllegalStateException(e);
}
return this;
}
/**
* Set the body as a byte array.
*/
public DefaultResponseCreator body(byte[] content) {
this.content = content;
return this;
}
/**
* Set the body as a {@link Resource}.
*/
public DefaultResponseCreator body(Resource resource) {
this.contentResource = resource;
return this;
}
/**
* Set the {@code Content-Type} header.
*/
public DefaultResponseCreator contentType(MediaType mediaType) {
if (mediaType != null) {
this.headers.setContentType(mediaType);
}
return this;
}
/**
* Set the {@code Location} header.
*/
public DefaultResponseCreator location(URI location) {
this.headers.setLocation(location);
return this;
}
/**
* Copy all given headers.
*/
public DefaultResponseCreator headers(HttpHeaders headers) {
for (String headerName : headers.keySet()) {
for (String headerValue : headers.get(headerName)) {
this.headers.add(headerName, headerValue);
}
}
return this;
}
}
/*
* Copyright 2002-2012 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.mock.client.response;
import java.io.IOException;
import java.net.URI;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.test.web.mock.client.ResponseCreator;
/**
* Static factory methods for obtaining a {@link ResponseCreator} instance.
*
* <p><strong>Eclipse users:</strong> consider adding this class as a Java editor
* favorite. To navigate, open the Preferences and type "favorites".
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class ResponseCreators {
private ResponseCreators() {
}
/**
* {@code ResponseCreator} for a 200 response (OK).
*/
public static DefaultResponseCreator withSuccess() {
return new DefaultResponseCreator(HttpStatus.OK);
}
/**
* {@code ResponseCreator} for a 200 response (OK) with String body.
* @param body the response body, a "UTF-8" string
* @param mediaType the type of the content, may be {@code null}
*/
public static DefaultResponseCreator withSuccess(String body, MediaType mediaType) {
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(mediaType);
}
/**
* {@code ResponseCreator} for a 200 response (OK) with byte[] body.
* @param body the response body
* @param mediaType the type of the content, may be {@code null}
*/
public static DefaultResponseCreator withSuccess(byte[] body, MediaType contentType) {
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(contentType);
}
/**
* {@code ResponseCreator} for a 200 response (OK) content with {@link Resource}-based body.
* @param body the response body
* @param mediaType the type of the content, may be {@code null}
*/
public static DefaultResponseCreator withSuccess(Resource body, MediaType contentType) {
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(contentType);
}
/**
* {@code ResponseCreator} for a 201 response (CREATED) with a 'Location' header.
* @param location the value for the {@code Location} header
*/
public static DefaultResponseCreator withCreatedEntity(URI location) {
return new DefaultResponseCreator(HttpStatus.CREATED).location(location);
}
/**
* {@code ResponseCreator} for a 204 response (NO_CONTENT).
*/
public static DefaultResponseCreator withNoContent() {
return new DefaultResponseCreator(HttpStatus.NO_CONTENT);
}
/**
* {@code ResponseCreator} for a 400 response (BAD_REQUEST).
*/
public static DefaultResponseCreator withBadRequest() {
return new DefaultResponseCreator(HttpStatus.BAD_REQUEST);
}
/**
* {@code ResponseCreator} for a 401 response (UNAUTHORIZED).
*/
public static DefaultResponseCreator withUnauthorizedRequest() {
return new DefaultResponseCreator(HttpStatus.UNAUTHORIZED);
}
/**
* {@code ResponseCreator} for a 500 response (SERVER_ERROR).
*/
public static DefaultResponseCreator withServerError() {
return new DefaultResponseCreator(HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
* {@code ResponseCreator} with a specific HTTP status.
* @param status the response status
*/
public static DefaultResponseCreator withStatus(HttpStatus status) {
return new DefaultResponseCreator(status);
}
/**
* Respond with a given body, headers, status code, and status text.
*
* @param body the body of the response "UTF-8" encoded
* @param headers the response headers
* @param statusCode the response status code
* @param statusText the response status text
*
* @deprecated in favor of methods returning DefaultResponseCreator
*/
public static ResponseCreator withResponse(final String body, final HttpHeaders headers,
final HttpStatus statusCode, final String statusText) {
return new ResponseCreator() {
public MockClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
MockClientHttpResponse response = new MockClientHttpResponse(body.getBytes("UTF-8"), statusCode);
response.getHeaders().putAll(headers);
return response;
}
};
}
/**
* Respond with the given body, headers, and a status code of 200 (OK).
*
* @param body the body of the response "UTF-8" encoded
* @param headers the response headers
*
* @deprecated in favor of methods 'withXyz' in this class returning DefaultResponseCreator
*/
public static ResponseCreator withResponse(String body, HttpHeaders headers) {
return withResponse(body, headers, HttpStatus.OK, "");
}
/**
* Respond with a given body, headers, status code, and text.
*
* @param body a {@link Resource} containing the body of the response
* @param headers the response headers
* @param statusCode the response status code
* @param statusText the response status text
*
* @deprecated in favor of methods 'withXyz' in this class returning DefaultResponseCreator
*/
public static ResponseCreator withResponse(final Resource body, final HttpHeaders headers,
final HttpStatus statusCode, String statusText) {
return new ResponseCreator() {
public MockClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
MockClientHttpResponse response = new MockClientHttpResponse(body.getInputStream(), statusCode);
response.getHeaders().putAll(headers);
return response;
}
};
}
/**
* Respond with the given body, headers, and a status code of 200 (OK).
* @param body the body of the response
* @param headers the response headers
*
* @deprecated in favor of methods 'withXyz' in this class returning DefaultResponseCreator
*/
public static ResponseCreator withResponse(final Resource body, final HttpHeaders headers) {
return withResponse(body, headers, HttpStatus.OK, "");
}
}
/*
* Copyright 2002-2012 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.
*/
/**
* Contains built-in {@link org.springframework.test.web.mock.client.ResponseCreator}
* implementations. Use
* {@link org.springframework.test.web.mock.client.response.ResponseCreators}
* to gain access to instances of those implementations.
*/
package org.springframework.test.web.mock.client.response;
/*
* Copyright 2002-2012 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.mock.servlet;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;
/**
* A simple implementation of {@link MvcResult} with setters.
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @since 3.2
*/
class DefaultMvcResult implements MvcResult {
private final MockHttpServletRequest mockRequest;
private final MockHttpServletResponse mockResponse;
private Object handler;
private HandlerInterceptor[] interceptors;
private ModelAndView modelAndView;
private Exception resolvedException;
/**
* Create a new instance with the given request and response.
*/
public DefaultMvcResult(MockHttpServletRequest request, MockHttpServletResponse response) {
this.mockRequest = request;
this.mockResponse = response;
}
public MockHttpServletResponse getResponse() {
return mockResponse;
}
public MockHttpServletRequest getRequest() {
return mockRequest;
}
public Object getHandler() {
return this.handler;
}
public void setHandler(Object handler) {
this.handler = handler;
}
public HandlerInterceptor[] getInterceptors() {
return this.interceptors;
}
public void setInterceptors(HandlerInterceptor[] interceptors) {
this.interceptors = interceptors;
}
public Exception getResolvedException() {
return this.resolvedException;
}
public void setResolvedException(Exception resolvedException) {
this.resolvedException = resolvedException;
}
public ModelAndView getModelAndView() {
return this.modelAndView;
}
public void setModelAndView(ModelAndView mav) {
this.modelAndView = mav;
}
public FlashMap getFlashMap() {
return RequestContextUtils.getOutputFlashMap(mockRequest);
}
}
/*
* Copyright 2002-2012 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.mock.servlet;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import org.springframework.beans.Mergeable;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.Assert;
/**
* <strong>Main entry point for server-side Spring MVC test support.</strong>
*
* <p>Below is an example:
*
* <pre>
* static imports:
* MockMvcBuilders.*, MockMvcRequestBuilders.*, MockMvcResultMatchers.*
*
* WebApplicationContext wac = ...;
*
* MockMvc mockMvc = webAppContextSetup(wac).configureWarRootDir("src/main/webapp", false).build()
*
* mockMvc.perform(get("/form"))
* .andExpect(status().isOk())
* .andExpect(content().mimeType("text/html"))
* .andExpect(forwardedUrl("/WEB-INF/layouts/main.jsp"));
* </pre>
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @since 3.2
*/
public final class MockMvc {
static String MVC_RESULT_ATTRIBUTE = MockMvc.class.getName().concat(".MVC_RESULT_ATTRIBUTE");
private final MockFilterChain filterChain;
private final ServletContext servletContext;
private RequestBuilder defaultRequestBuilder;
private List<ResultMatcher> defaultResultMatchers = new ArrayList<ResultMatcher>();
private List<ResultHandler> defaultResultHandlers = new ArrayList<ResultHandler>();
/**
* Private constructor, not for direct instantiation.
* @see org.springframework.test.web.mock.servlet.setup.MockMvcBuilders
*/
MockMvc(MockFilterChain filterChain, ServletContext servletContext) {
Assert.notNull(servletContext, "A ServletContext is required");
Assert.notNull(filterChain, "A MockFilterChain is required");
this.filterChain = filterChain;
this.servletContext = servletContext;
}
/**
* A default request builder merged into every performed request.
* @see org.springframework.test.web.mock.servlet.setup.DefaultMockMvcBuilder#defaultRequest(RequestBuilder)
*/
void setDefaultRequest(RequestBuilder requestBuilder) {
this.defaultRequestBuilder = requestBuilder;
}
/**
* Expectations to assert after every performed request.
* @see org.springframework.test.web.mock.servlet.setup.DefaultMockMvcBuilder#alwaysExpect(ResultMatcher)
*/
void setGlobalResultMatchers(List<ResultMatcher> resultMatchers) {
Assert.notNull(resultMatchers, "resultMatchers is required");
this.defaultResultMatchers = resultMatchers;
}
/**
* General actions to apply after every performed request.
* @see org.springframework.test.web.mock.servlet.setup.DefaultMockMvcBuilder#alwaysDo(ResultHandler)
*/
void setGlobalResultHandlers(List<ResultHandler> resultHandlers) {
Assert.notNull(resultHandlers, "resultHandlers is required");
this.defaultResultHandlers = resultHandlers;
}
/**
* 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.mock.servlet.request.MockMvcRequestBuilders}
*
* @return an instance of {@link ResultActions}; never {@code null}
*
* @see org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders
* @see org.springframework.test.web.mock.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);
}
}
MockHttpServletRequest request = requestBuilder.buildRequest(this.servletContext);
MockHttpServletResponse response = new MockHttpServletResponse();
final MvcResult mvcResult = new DefaultMvcResult(request, response);
request.setAttribute(MVC_RESULT_ATTRIBUTE, mvcResult);
this.filterChain.reset();
this.filterChain.doFilter(request, response);
applyDefaultResultActions(mvcResult);
return new ResultActions() {
public ResultActions andExpect(ResultMatcher matcher) throws Exception {
matcher.match(mvcResult);
return this;
}
public ResultActions andDo(ResultHandler printer) throws Exception {
printer.handle(mvcResult);
return this;
}
public MvcResult andReturn() {
return mvcResult;
}
};
}
private void applyDefaultResultActions(MvcResult mvcResult) throws Exception {
for (ResultMatcher matcher : this.defaultResultMatchers) {
matcher.match(mvcResult);
}
for (ResultHandler handler : this.defaultResultHandlers) {
handler.handle(mvcResult);
}
}
}
/*
* Copyright 2002-2012 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.mock.servlet;
/**
* Builds a {@link MockMvc}.
*
* <p>See static, factory methods in
* {@code org.springframework.test.web.server.setup.MockMvcBuilders}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface MockMvcBuilder {
/**
* Build a {@link MockMvc} instance.
*/
MockMvc build();
}
\ No newline at end of file
/*
* Copyright 2002-2012 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.mock.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.mock.web.MockFilterChain;
import org.springframework.mock.web.MockServletConfig;
import org.springframework.web.context.WebApplicationContext;
/**
* Base class for MockMvc builder implementations, providing the capability to
* create a {@link MockMvc} instance.
*
* <p>{@link org.springframework.test.web.mock.servlet.setup.DefaultMockMvcBuilder},
* which derives from this class, provides a concrete {@code build} method,
* and delegates to abstract methods to obtain a {@link WebApplicationContext}.
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @since 3.2
*/
public abstract class MockMvcBuilderSupport {
protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig,
WebApplicationContext webAppContext, RequestBuilder defaultRequestBuilder,
List<ResultMatcher> globalResultMatchers, List<ResultHandler> globalResultHandlers) {
ServletContext servletContext = webAppContext.getServletContext();
TestDispatcherServlet dispatcherServlet = new TestDispatcherServlet(webAppContext);
try {
dispatcherServlet.init(servletConfig);
}
catch (ServletException ex) {
// should never happen..
throw new MockMvcBuildException("Failed to initialize TestDispatcherServlet", ex);
}
MockFilterChain filterChain = new MockFilterChain(dispatcherServlet, filters);
MockMvc mockMvc = new MockMvc(filterChain, servletContext);
mockMvc.setDefaultRequest(defaultRequestBuilder);
mockMvc.setGlobalResultMatchers(globalResultMatchers);
mockMvc.setGlobalResultHandlers(globalResultHandlers);
return mockMvc;
}
@SuppressWarnings("serial")
private static class MockMvcBuildException extends NestedRuntimeException {
public MockMvcBuildException(String msg, Throwable cause) {
super(msg, cause);
}
}
}
/*
* Copyright 2002-2012 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.mock.servlet;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* Provides access to the result of an executed request.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface MvcResult {
/**
* Return the performed request.
* @return the request, never {@code null}
*/
MockHttpServletRequest getRequest();
/**
* Return the resulting response.
* @return the response, never {@code null}
*/
MockHttpServletResponse getResponse();
/**
* Return the executed handler.
* @return the handler, possibly {@code null} if none were executed
*/
Object getHandler();
/**
* Return interceptors around the handler.
* @return interceptors, or {@code null} if none were selected
*/
HandlerInterceptor[] getInterceptors();
/**
* Return the {@code ModelAndView} prepared by the handler.
* @return a {@code ModelAndView}, or {@code null}
*/
ModelAndView getModelAndView();
/**
* Return any exception raised by a handler and successfully resolved
* through a {@link HandlerExceptionResolver}.
*
* @return an exception, possibly {@code null}
*/
Exception getResolvedException();
/**
* Return the "output" flash attributes saved during request processing.
* @return the {@code FlashMap}, possibly empty
*/
FlashMap getFlashMap();
}
package org.springframework.test.web.mock.servlet;
import javax.servlet.ServletContext;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* Builds a {@link MockHttpServletRequest}.
*
* <p>See static, factory methods in
* {@code org.springframework.test.web.server.request.MockMvcRequestBuilders}.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface RequestBuilder {
/**
* Build the request.
*
* @param servletContext the {@link ServletContext} to use to create the request
* @return the request
*/
MockHttpServletRequest buildRequest(ServletContext servletContext);
}
/*
* Copyright 2002-2012 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.mock.servlet;
/**
* Allows applying actions, such as expectations, on the result of an executed
* request.
*
* <p>See static factory methods in
* {@code org.springframework.test.web.server.result.MockMvcResultMatchers}
* {@code org.springframework.test.web.server.result.MockMvcResultHandlers}
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface ResultActions {
/**
* Provide an expectation. For example:
* <pre>
* static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
*
* mockMvc.perform(get("/person/1"))
* .andExpect(status.isOk())
* .andExpect(content().mimeType(MediaType.APPLICATION_JSON))
* .andExpect(jsonPath("$.person.name").equalTo("Jason"));
*
* mockMvc.perform(post("/form"))
* .andExpect(status.isOk())
* .andExpect(redirectedUrl("/person/1"))
* .andExpect(model().size(1))
* .andExpect(model().attributeExists("person"))
* .andExpect(flash().attributeCount(1))
* .andExpect(flash().attribute("message", "success!"));
* </pre>
*/
ResultActions andExpect(ResultMatcher matcher) throws Exception;
/**
* Provide a general action. For example:
* <pre>
* static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
*
* mockMvc.perform(get("/form")).andDo(print());
* </pre>
*/
ResultActions andDo(ResultHandler handler) throws Exception;
/**
* Return the result of the executed request for direct access to the results.
*
* @return the result of the request
*/
MvcResult andReturn();
}
\ No newline at end of file
/*
* Copyright 2002-2012 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.mock.servlet;
/**
* Executes a generic action (e.g. printing debug information) on the result of
* an executed request.
*
* <p>See static factory methods in
* {@code org.springframework.test.web.server.result.MockMvcResultHandlers}.
*
* <p>Example:
*
* <pre>
* static imports: MockMvcRequestBuilders.*, MockMvcResultHandlers.*
*
* mockMvc.perform(get("/form")).andDo(print());
* </pre>
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface ResultHandler {
/**
* Apply the action on the given result.
*
* @param result the result of the executed request
* @throws Exception if a failure occurs
*/
void handle(MvcResult result) throws Exception;
}
/*
* Copyright 2002-2012 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.mock.servlet;
/**
* Matches the result of an executed request against some expectation.
*
* <p>See static factory methods in
* {@code org.springframework.test.web.server.result.MockMvcResultMatchers}.
*
* <p>Example:
*
* <pre>
* static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
*
* mockMvc.perform(get("/form"))
* .andExpect(status.isOk())
* .andExpect(content().mimeType(MediaType.APPLICATION_JSON));
* </pre>
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public interface ResultMatcher {
/**
* Assert the result of an executed request.
*
* @param mvcResult the result of the executed request
* @throws Exception if a failure occurs
*/
void match(MvcResult result) throws Exception;
}
/*
* Copyright 2002-2012 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.mock.servlet;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView;
/**
* A sub-class of {@code DispatcherServlet} that saves the result in an
* {@link MvcResult}. The {@code MvcResult} instance is expected to be available
* as the request attribute {@link MockMvc#MVC_RESULT_ATTRIBUTE}.
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @since 3.2
*/
@SuppressWarnings("serial")
final class TestDispatcherServlet extends DispatcherServlet {
/**
* Create a new instance with the given web application context.
*/
public TestDispatcherServlet(WebApplicationContext webApplicationContext) {
super(webApplicationContext);
}
protected DefaultMvcResult getMvcResult(ServletRequest request) {
return (DefaultMvcResult) request.getAttribute(MockMvc.MVC_RESULT_ATTRIBUTE);
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
TestCallableInterceptor callableInterceptor = new TestCallableInterceptor();
asyncManager.registerCallableInterceptor("mock-mvc", callableInterceptor);
TestDeferredResultInterceptor deferredResultInterceptor = new TestDeferredResultInterceptor();
asyncManager.registerDeferredResultInterceptor("mock-mvc", deferredResultInterceptor);
super.service(request, response);
Object handler = getMvcResult(request).getHandler();
if (asyncManager.isConcurrentHandlingStarted() && !deferredResultInterceptor.wasInvoked) {
if (!callableInterceptor.await()) {
throw new ServletException(
"Gave up waiting on Callable from [" + handler.getClass().getName() + "] to complete");
}
}
}
@Override
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
HandlerExecutionChain chain = super.getHandler(request);
if (chain != null) {
DefaultMvcResult mvcResult = getMvcResult(request);
mvcResult.setHandler(chain.getHandler());
mvcResult.setInterceptors(chain.getInterceptors());
}
return chain;
}
@Override
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
throws Exception {
DefaultMvcResult mvcResult = getMvcResult(request);
mvcResult.setModelAndView(mv);
super.render(mv, request, response);
}
@Override
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
ModelAndView mav = super.processHandlerException(request, response, handler, ex);
// We got this far, exception was processed..
DefaultMvcResult mvcResult = getMvcResult(request);
mvcResult.setResolvedException(ex);
mvcResult.setModelAndView(mav);
return mav;
}
private final class TestCallableInterceptor implements CallableProcessingInterceptor {
private final CountDownLatch latch = new CountDownLatch(1);
private boolean await() {
try {
return this.latch.await(5, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
return false;
}
}
public void preProcess(NativeWebRequest request, Callable<?> task) { }
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
this.latch.countDown();
}
}
private final class TestDeferredResultInterceptor implements DeferredResultProcessingInterceptor {
private boolean wasInvoked;
public void preProcess(NativeWebRequest request, DeferredResult<?> deferredResult) {
this.wasInvoked = true;
}
public void postProcess(NativeWebRequest request, DeferredResult<?> deferredResult, Object concurrentResult) { }
public void afterExpiration(NativeWebRequest request, DeferredResult<?> deferredResult) { }
}
}
/*
* Copyright 2002-2012 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.
*/
/**
* Contains server-side support for testing Spring MVC applications.
* @see org.springframework.test.web.mock.servlet.MockMvc
*/
package org.springframework.test.web.mock.servlet;
/*
* Copyright 2002-2012 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.mock.servlet.request;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.util.WebUtils;
/**
* Mock implementation of the {@link AsyncContext} interface.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
class MockAsyncContext implements AsyncContext {
private final ServletRequest request;
private final ServletResponse response;
private final List<AsyncListener> listeners = new ArrayList<AsyncListener>();
private String dispatchedPath;
private long timeout = 10 * 60 * 1000L; // 10 seconds is Tomcat's default
public MockAsyncContext(ServletRequest request, ServletResponse response) {
this.request = request;
this.response = response;
}
public ServletRequest getRequest() {
return this.request;
}
public ServletResponse getResponse() {
return this.response;
}
public boolean hasOriginalRequestAndResponse() {
return (this.request instanceof MockHttpServletRequest) && (this.response instanceof MockHttpServletResponse);
}
public String getDispatchedPath() {
return this.dispatchedPath;
}
public void dispatch() {
dispatch(null);
}
public void dispatch(String path) {
dispatch(null, path);
}
public void dispatch(ServletContext context, String path) {
this.dispatchedPath = path;
}
public void complete() {
Servlet3MockHttpServletRequest mockRequest = WebUtils.getNativeRequest(request, Servlet3MockHttpServletRequest.class);
if (mockRequest != null) {
mockRequest.setAsyncStarted(false);
}
for (AsyncListener listener : this.listeners) {
try {
listener.onComplete(new AsyncEvent(this, this.request, this.response));
}
catch (IOException e) {
throw new IllegalStateException("AsyncListener failed", e);
}
}
}
public void start(Runnable runnable) {
runnable.run();
}
public List<AsyncListener> getListeners() {
return this.listeners;
}
public void addListener(AsyncListener listener) {
this.listeners.add(listener);
}
public void addListener(AsyncListener listener, ServletRequest request, ServletResponse response) {
this.listeners.add(listener);
}
public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
return BeanUtils.instantiateClass(clazz);
}
public long getTimeout() {
return this.timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
}
/*
* Copyright 2002-2012 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.mock.servlet.request;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
import org.springframework.util.ClassUtils;
/**
* Default builder for {@link MockMultipartHttpServletRequest}.
*
* @author Rossen Stoyanchev
* @author Arjen Poutsma
* @since 3.2
*/
public class MockMultipartHttpServletRequestBuilder extends MockHttpServletRequestBuilder {
private final List<MockMultipartFile> files = new ArrayList<MockMultipartFile>();
/**
* Package private constructor. Use static factory methods in
* {@link MockMvcRequestBuilders}.
*
* <p>For other ways to initialize a {@code MockMultipartHttpServletRequest},
* see {@link #with(RequestPostProcessor)} and the
* {@link RequestPostProcessor} extension point.
*/
MockMultipartHttpServletRequestBuilder(URI uri) {
super(uri, HttpMethod.POST);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
/**
* Create a new MockMultipartFile with the given content.
*
* @param name the name of the file
* @param content the content of the file
*/
public MockMultipartHttpServletRequestBuilder file(String name, byte[] content) {
this.files.add(new MockMultipartFile(name, content));
return this;
}
/**
* Add the given MockMultipartFile.
*
* @param file the multipart file
*/
public MockMultipartHttpServletRequestBuilder file(MockMultipartFile file) {
this.files.add(file);
return this;
}
@Override
public Object merge(Object parent) {
if (parent == null) {
return this;
}
if (!(parent instanceof MockMultipartHttpServletRequestBuilder)) {
throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]");
}
super.merge(parent);
MockMultipartHttpServletRequestBuilder parentBuilder = (MockMultipartHttpServletRequestBuilder) parent;
this.files.addAll(parentBuilder.files);
return this;
}
@Override
protected final MockHttpServletRequest createServletRequest(ServletContext servletContext) {
MockMultipartHttpServletRequest request = ClassUtils.hasMethod(ServletRequest.class, "startAsync") ?
createServlet3Request() : new MockMultipartHttpServletRequest();
for (MockMultipartFile file : this.files) {
request.addFile(file);
}
return request;
}
private static MockMultipartHttpServletRequest createServlet3Request() {
try {
String className = "org.springframework.test.web.mock.servlet.request.Servlet3MockMultipartHttpServletRequest";
Class<?> clazz = ClassUtils.forName(className, MockMultipartHttpServletRequestBuilder.class.getClassLoader());
Constructor<?> constructor = clazz.getConstructor(ServletContext.class);
return (MockMultipartHttpServletRequest) BeanUtils.instantiateClass(constructor);
}
catch (Throwable t) {
throw new IllegalStateException("Failed to instantiate MockHttpServletRequest", t);
}
}
}
/*
* Copyright 2002-2012 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.mock.servlet.request;
import java.net.URI;
import org.springframework.http.HttpMethod;
import org.springframework.test.web.mock.servlet.RequestBuilder;
import org.springframework.web.util.UriTemplate;
/**
* Static factory methods for {@link RequestBuilder}s.
*
* <p><strong>Eclipse users:</strong> consider adding this class as a Java
* editor favorite. To navigate, open the Preferences and type "favorites".
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class MockMvcRequestBuilders {
private MockMvcRequestBuilders() {
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a GET request.
*
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
public static MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables) {
return request(HttpMethod.GET, urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a POST request.
*
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
public static MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables) {
return request(HttpMethod.POST, urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a PUT request.
*
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
public static MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables) {
return request(HttpMethod.PUT, urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a DELETE request.
*
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
public static MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) {
return request(HttpMethod.DELETE, urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a multipart request.
*
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
public static MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables) {
URI url = expandUrl(urlTemplate, urlVariables);
return new MockMultipartHttpServletRequestBuilder(url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for any HTTP method.
*
* @param httpMethod the HTTP method
* @param urlTemplate a URI template including any component (e.g. scheme, host, query)
* @param urlVariables zero or more URI variables
*/
private static MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables) {
URI url = expandUrl(urlTemplate, urlVariables);
return new MockHttpServletRequestBuilder(url, httpMethod);
}
private static URI expandUrl(String urlTemplate, Object[] urlVariables) {
UriTemplate uriTemplate = new UriTemplate(urlTemplate);
return uriTemplate.expand(urlVariables);
}
}
/*
* Copyright 2002-2012 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.mock.servlet.request;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* Extension point for applications or 3rd party libraries that wish to further
* initialize a {@link MockHttpServletRequest} instance after it has been built
* by {@link MockHttpServletRequestBuilder} or its sub-class
* {@link MockMultipartHttpServletRequestBuilder}.
*
* <p>Implementations of this interface can be provided to
* {@link MockHttpServletRequestBuilder#with(RequestPostProcessor)} at the time
* when a request is about to be performed.
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @since 3.2
*/
public interface RequestPostProcessor {
/**
* Post-process the given {@code MockHttpServletRequest} after its creation
* and initialization through a {@code MockHttpServletRequestBuilder}.
*
* @param request the request to initialize
* @return the request to use, either the one passed in or a wrapped one;
*/
MockHttpServletRequest postProcessRequest(MockHttpServletRequest request);
}
/*
* Copyright 2002-2012 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.mock.servlet.request;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* A Servlet 3 sub-class of MockHttpServletRequest.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
class Servlet3MockHttpServletRequest extends MockHttpServletRequest {
private boolean asyncStarted;
private MockAsyncContext asyncContext;
private Map<String, Part> parts = new HashMap<String, Part>();
public Servlet3MockHttpServletRequest(ServletContext servletContext) {
super(servletContext);
}
public boolean isAsyncSupported() {
return true;
}
public AsyncContext startAsync() {
return startAsync(this, null);
}
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
this.asyncStarted = true;
this.asyncContext = new MockAsyncContext(request, response);
return this.asyncContext;
}
public AsyncContext getAsyncContext() {
return this.asyncContext;
}
public void setAsyncContext(MockAsyncContext asyncContext) {
this.asyncContext = asyncContext;
}
public DispatcherType getDispatcherType() {
return DispatcherType.REQUEST;
}
public boolean isAsyncStarted() {
return this.asyncStarted;
}
public void setAsyncStarted(boolean asyncStarted) {
this.asyncStarted = asyncStarted;
}
public void addPart(Part part) {
this.parts.put(part.getName(), part);
}
public Part getPart(String key) throws IOException, IllegalStateException, ServletException {
return this.parts.get(key);
}
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
return this.parts.values();
}
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
throw new UnsupportedOperationException();
}
}
/*
* Copyright 2002-2012 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.mock.servlet.request;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.springframework.mock.web.MockMultipartHttpServletRequest;
/**
* A Servlet 3 sub-class of MockMultipartHttpServletRequest.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
class Servlet3MockMultipartHttpServletRequest extends MockMultipartHttpServletRequest {
private boolean asyncStarted;
private MockAsyncContext asyncContext;
private Map<String, Part> parts = new HashMap<String, Part>();
public boolean isAsyncSupported() {
return true;
}
public AsyncContext startAsync() {
return startAsync(this, null);
}
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
this.asyncStarted = true;
this.asyncContext = new MockAsyncContext(request, response);
return this.asyncContext;
}
public AsyncContext getAsyncContext() {
return this.asyncContext;
}
public void setAsyncContext(MockAsyncContext asyncContext) {
this.asyncContext = asyncContext;
}
public DispatcherType getDispatcherType() {
return DispatcherType.REQUEST;
}
public boolean isAsyncStarted() {
return this.asyncStarted;
}
public void setAsyncStarted(boolean asyncStarted) {
this.asyncStarted = asyncStarted;
}
public void addPart(Part part) {
this.parts.put(part.getName(), part);
}
public Part getPart(String key) throws IOException, IllegalStateException, ServletException {
return this.parts.get(key);
}
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
return this.parts.values();
}
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
throw new UnsupportedOperationException();
}
}
/*
* Copyright 2002-2012 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.
*/
/**
* Contains built-in {@link org.springframework.test.web.mock.servlet.RequestBuilder}
* implementations. Use
* {@link org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders}
* to gain access to instances of those implementations.
*/
package org.springframework.test.web.mock.servlet.request;
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.http.MediaType;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
import org.springframework.test.web.mock.support.XmlExpectationsHelper;
import org.w3c.dom.Node;
/**
* Factory for response content assertions. An instance of this class is
* typically accessed via {@link MockMvcResultMatchers#content()}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class ContentResultMatchers {
private final XmlExpectationsHelper xmlHelper;
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#content()}.
*/
protected ContentResultMatchers() {
this.xmlHelper = new XmlExpectationsHelper();
}
/**
* Assert the ServletResponse content type.
*/
public ResultMatcher mimeType(String contentType) {
return mimeType(MediaType.parseMediaType(contentType));
}
/**
* Assert the ServletResponse content type after parsing it as a MediaType.
*/
public ResultMatcher mimeType(final MediaType contentType) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String actual = result.getResponse().getContentType();
assertTrue("Content type not set", actual != null);
assertEquals("Content type", contentType, MediaType.parseMediaType(actual));
}
};
}
/**
* Assert the character encoding in the ServletResponse.
* @see HttpServletResponse#getCharacterEncoding()
*/
public ResultMatcher encoding(final String characterEncoding) {
return new ResultMatcher() {
public void match(MvcResult result) {
String actual = result.getResponse().getCharacterEncoding();
assertEquals("Character encoding", characterEncoding, actual);
}
};
}
/**
* Assert the response body content with a Hamcrest {@link Matcher}.
* <pre>
* mockMvc.perform(get("/path"))
* .andExpect(content(containsString("text")));
* </pre>
*/
public ResultMatcher string(final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
MatcherAssert.assertThat("Response content", result.getResponse().getContentAsString(), matcher);
}
};
}
/**
* Assert the response body content as a String.
*/
public ResultMatcher string(String content) {
return string(Matchers.equalTo(content));
}
/**
* Assert the response body content as a byte array.
*/
public ResultMatcher bytes(final byte[] expectedContent) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
byte[] content = result.getResponse().getContentAsByteArray();
MatcherAssert.assertThat("Response content", content, Matchers.equalTo(expectedContent));
}
};
}
/**
* Parse the response content and the given string as XML and assert the two
* are "similar" - i.e. they contain the same elements and attributes
* regardless of order.
*
* <p>Use of this matcher requires the <a
* href="http://xmlunit.sourceforge.net/">XMLUnit<a/> library.
*
* @param xmlContent the expected XML content
* @see MockMvcResultMatchers#xpath(String, Object...)
* @see MockMvcResultMatchers#xpath(String, Map, Object...)
*/
public ResultMatcher xml(final String xmlContent) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
xmlHelper.assertXmlEqual(xmlContent, content);
}
};
}
/**
* Parse the response content as {@link Node} and apply the given Hamcrest
* {@link Matcher}.
*
* @see org.hamcrest.Matchers#hasXPath
*/
public ResultMatcher node(final Matcher<? super Node> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
xmlHelper.assertNode(content, matcher);
}
};
}
/**
* Parse the response content as {@link DOMSource} and apply the given
* Hamcrest {@link Matcher}.
*
* @see <a href="http://code.google.com/p/xml-matchers/">xml-matchers</a>
*/
public ResultMatcher source(final Matcher<? super Source> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
xmlHelper.assertSource(content, matcher);
}
};
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
import javax.servlet.http.Cookie;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
/**
* Factory for response cookie assertions. An instance of this class is
* typically accessed via {@link MockMvcResultMatchers#cookie()}.
*
* @author Rossen Stoyanchev
* @author Thomas Bruyelle
* @since 3.2
*/
public class CookieResultMatchers {
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#cookie()}.
*/
protected CookieResultMatchers() {
}
/**
* Assert a cookie value with the given Hamcrest {@link Matcher}.
*/
public ResultMatcher value(final String name, final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) {
Cookie cookie = result.getResponse().getCookie(name);
assertTrue("Response cookie not found: " + name, cookie != null);
MatcherAssert.assertThat("Response cookie", cookie.getValue(), matcher);
}
};
}
/**
* Assert a cookie value.
*/
public ResultMatcher value(String name, String value) {
return value(name, Matchers.equalTo(value));
}
/**
* Assert a cookie exists. The existence check is irrespective of whether
* max age is 0 (i.e. expired).
*/
public ResultMatcher exists(final String name) {
return new ResultMatcher() {
public void match(MvcResult result) {
Cookie cookie = result.getResponse().getCookie(name);
assertTrue("No cookie with name: " + name, cookie != null);
}
};
}
/**
* Assert a cookie does not exist. Note that the existence check is
* irrespective of whether max age is 0, i.e. expired.
*/
public ResultMatcher doesNotExist(final String name) {
return new ResultMatcher() {
public void match(MvcResult result) {
Cookie cookie = result.getResponse().getCookie(name);
assertTrue("Unexpected cookie with name " + name, cookie == null);
}
};
}
/**
* Assert a cookie's maxAge with a Hamcrest {@link Matcher}.
*/
public ResultMatcher maxAge(final String name, final Matcher<? super Integer> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) {
Cookie cookie = result.getResponse().getCookie(name);
assertTrue("No cookie with name: " + name, cookie != null);
MatcherAssert.assertThat("Response cookie maxAge", cookie.getMaxAge(), matcher);
}
};
}
/**
* Assert a cookie's maxAge value.
*/
public ResultMatcher maxAge(String name, int maxAge) {
return maxAge(name, Matchers.equalTo(maxAge));
}
/**
* Assert a cookie path with a Hamcrest {@link Matcher}.
*/
public ResultMatcher path(final String name, final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Cookie cookie = result.getResponse().getCookie(name);
MatcherAssert.assertThat("Response cookie path", cookie.getPath(), matcher);
}
};
}
public ResultMatcher path(String name, String path) {
return path(name, Matchers.equalTo(path));
}
/**
* Assert a cookie's domain with a Hamcrest {@link Matcher}.
*/
public ResultMatcher domain(final String name, final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Cookie cookie = result.getResponse().getCookie(name);
MatcherAssert.assertThat("Response cookie domain", cookie.getDomain(), matcher);
}
};
}
/**
* Assert a cookie's domain value.
*/
public ResultMatcher domain(String name, String domain) {
return domain(name, Matchers.equalTo(domain));
}
/**
* Assert a cookie's comment with a Hamcrest {@link Matcher}.
*/
public ResultMatcher comment(final String name, final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Cookie cookie = result.getResponse().getCookie(name);
MatcherAssert.assertThat("Response cookie comment", cookie.getComment(), matcher);
}
};
}
/**
* Assert a cookie's comment value.
*/
public ResultMatcher comment(String name, String comment) {
return comment(name, Matchers.equalTo(comment));
}
/**
* Assert a cookie's version with a Hamcrest {@link Matcher}
*/
public ResultMatcher version(final String name, final Matcher<? super Integer> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Cookie cookie = result.getResponse().getCookie(name);
MatcherAssert.assertThat("Response cookie version", cookie.getVersion(), matcher);
}
};
}
/**
* Assert a cookie's version value.
*/
public ResultMatcher version(String name, int version) {
return version(name, Matchers.equalTo(version));
}
/**
* Assert whether the cookie must be sent over a secure protocol or not.
*/
public ResultMatcher secure(final String name, final boolean secure) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Cookie cookie = result.getResponse().getCookie(name);
assertEquals("Response cookie secure", secure, cookie.getSecure());
}
};
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.*;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
/**
* Factory for "output" flash attribute assertions. An instance of this class is
* typically accessed via {@link MockMvcResultMatchers#flash()}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class FlashAttributeResultMatchers {
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#flash()}.
*/
protected FlashAttributeResultMatchers() {
}
/**
* Assert a flash attribute's value with the given Hamcrest {@link Matcher}.
*/
public <T> ResultMatcher attribute(final String name, final Matcher<T> matcher) {
return new ResultMatcher() {
@SuppressWarnings("unchecked")
public void match(MvcResult result) throws Exception {
MatcherAssert.assertThat("Flash attribute", (T) result.getFlashMap().get(name), matcher);
}
};
}
/**
* Assert a flash attribute's value.
*/
public <T> ResultMatcher attribute(final String name, final Object value) {
return attribute(name, Matchers.equalTo(value));
}
/**
* Assert the existence of the given flash attributes.
*/
public <T> ResultMatcher attributeExists(final String... names) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
for (String name : names) {
attribute(name, Matchers.notNullValue()).match(result);
}
}
};
}
/**
* Assert the number of flash attributes.
*/
public <T> ResultMatcher attributeCount(final int count) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
assertEquals("FlashMap size", count, result.getFlashMap().size());
}
};
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
import java.lang.reflect.Method;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
* Factory for assertions on the selected handler. An instance of this class is
* typically accessed via {@link MockMvcResultMatchers#handler()}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class HandlerResultMatchers {
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#handler()}.
*/
protected HandlerResultMatchers() {
}
/**
* Assert the type of the handler that processed the request.
*/
public ResultMatcher handlerType(final Class<?> type) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Object handler = result.getHandler();
assertTrue("No handler: ", handler != null);
Class<?> actual = handler.getClass();
if (HandlerMethod.class.isInstance(handler)) {
actual = ((HandlerMethod) handler).getBeanType();
}
assertEquals("Handler type", type, ClassUtils.getUserClass(actual));
}
};
}
/**
* Assert the name of the controller method that processed the request with
* the given Hamcrest {@link Matcher}.
*
* <p>Use of this method implies annotated controllers are processed with
* {@link RequestMappingHandlerMapping} and {@link RequestMappingHandlerAdapter}.
*/
public ResultMatcher methodName(final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Object handler = result.getHandler();
assertTrue("No handler: ", handler != null);
assertTrue("Not a HandlerMethod: " + handler, HandlerMethod.class.isInstance(handler));
MatcherAssert.assertThat("HandlerMethod", ((HandlerMethod) handler).getMethod().getName(), matcher);
}
};
}
/**
* Assert the name of the controller method that processed the request.
*
* <p>Use of this method implies annotated controllers are processed with
* {@link RequestMappingHandlerMapping} and {@link RequestMappingHandlerAdapter}.
*/
public ResultMatcher methodName(final String name) {
return methodName(Matchers.equalTo(name));
}
/**
* Assert the controller method that processed the request.
*
* <p>Use of this method implies annotated controllers are processed with
* {@link RequestMappingHandlerMapping} and {@link RequestMappingHandlerAdapter}.
*/
public ResultMatcher method(final Method method) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
Object handler = result.getHandler();
assertTrue("No handler: ", handler != null);
assertTrue("Not a HandlerMethod: " + handler, HandlerMethod.class.isInstance(handler));
assertEquals("HandlerMethod", method, ((HandlerMethod) handler).getMethod());
}
};
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
/**
* Factory for response header assertions. An instance of this
* class is usually accessed via {@link MockMvcResultMatchers#header()}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class HeaderResultMatchers {
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#header()}.
*/
protected HeaderResultMatchers() {
}
/**
* Assert a response header with the given Hamcrest {@link Matcher}.
*/
public ResultMatcher string(final String name, final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) {
MatcherAssert.assertThat("Response header", result.getResponse().getHeader(name), matcher);
}
};
}
/**
* Assert the primary value of a response header as a {@link String}.
*/
public ResultMatcher string(final String name, final String value) {
return string(name, Matchers.equalTo(value));
}
/**
* Assert the primary value of a response header as a {@link Long}.
*/
public ResultMatcher longValue(final String name, final long value) {
return new ResultMatcher() {
public void match(MvcResult result) {
assertEquals("Response header " + name, value, Long.parseLong(result.getResponse().getHeader(name)));
}
};
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import java.util.List;
import org.hamcrest.Matcher;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
import org.springframework.test.web.mock.support.JsonPathExpectationsHelper;
/**
* Factory for assertions on the response content using <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expressions.
* An instance of this class is typically accessed via
* {@link MockMvcResultMatchers#jsonPpath}.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class JsonPathResultMatchers {
private JsonPathExpectationsHelper jsonPathHelper;
/**
* Protected constructor. Use
* {@link MockMvcResultMatchers#jsonPath(String, Object...)} or
* {@link MockMvcResultMatchers#jsonPath(String, Matcher)}.
*/
protected JsonPathResultMatchers(String expression, Object ... args) {
this.jsonPathHelper = new JsonPathExpectationsHelper(expression, args);
}
/**
* Evaluate the JSONPath and assert the value of the content found with the
* given Hamcrest {@code Matcher}.
*/
public <T> ResultMatcher value(final Matcher<T> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
jsonPathHelper.assertValue(content, matcher);
}
};
}
/**
* Evaluate the JSONPath and assert the value of the content found.
*/
public ResultMatcher value(Object value) {
return value(equalTo(value));
}
/**
* Evaluate the JSONPath and assert that content exists.
*/
public ResultMatcher exists() {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
jsonPathHelper.exists(content);
}
};
}
/**
* Evaluate the JSON path and assert not content was found.
*/
public ResultMatcher doesNotExist() {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
jsonPathHelper.doesNotExist(content);
}
};
}
/**
* Evluate the JSON path and assert the content found is an array.
*/
public ResultMatcher isArray() {
return value(instanceOf(List.class));
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultHandler;
import org.springframework.util.CollectionUtils;
/**
* Static, factory methods for {@link ResultHandler}-based result actions.
*
* <p><strong>Eclipse users:</strong> consider adding this class as a Java editor
* favorite. To navigate, open the Preferences and type "favorites".
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class MockMvcResultHandlers {
private MockMvcResultHandlers() {
}
/**
* Print {@link MvcResult} details to the "standard" output stream.
*/
public static ResultHandler print() {
return new ConsolePrintingResultHandler();
}
/** An {@link PrintingResultHandler} that writes to the "standard" output stream */
private static class ConsolePrintingResultHandler extends PrintingResultHandler {
public ConsolePrintingResultHandler() {
super(new ResultValuePrinter() {
public void printHeading(String heading) {
System.out.println();
System.out.println(String.format("%20s:", heading));
}
public void printValue(String label, Object value) {
if (value != null && value.getClass().isArray()) {
value = CollectionUtils.arrayToList(value);
}
System.out.println(String.format("%20s = %s", label, value));
}
});
}
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
import java.util.Map;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.Matcher;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
/**
* Static, factory methods for {@link ResultMatcher}-based result actions.
*
* <p><strong>Eclipse users:</strong> consider adding this class as a Java editor
* favorite. To navigate, open the Preferences and type "favorites".
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public abstract class MockMvcResultMatchers {
private MockMvcResultMatchers() {
}
/**
* Access to request-related assertions.
*/
public static RequestResultMatchers request() {
return new RequestResultMatchers();
}
/**
* Access to assertions for the handler that handled the request.
*/
public static HandlerResultMatchers handler() {
return new HandlerResultMatchers();
}
/**
* Access to model-related assertions.
*/
public static ModelResultMatchers model() {
return new ModelResultMatchers();
}
/**
* Access to assertions on the selected view.
*/
public static ViewResultMatchers view() {
return new ViewResultMatchers();
}
/**
* Access to flash attribute assertions.
*/
public static FlashAttributeResultMatchers flash() {
return new FlashAttributeResultMatchers();
}
/**
* Asserts the request was forwarded to the given URL.
*/
public static ResultMatcher forwardedUrl(final String expectedUrl) {
return new ResultMatcher() {
public void match(MvcResult result) {
assertEquals("Forwarded URL", expectedUrl, result.getResponse().getForwardedUrl());
}
};
}
/**
* Asserts the request was redirected to the given URL.
*/
public static ResultMatcher redirectedUrl(final String expectedUrl) {
return new ResultMatcher() {
public void match(MvcResult result) {
assertEquals("Redirected URL", expectedUrl, result.getResponse().getRedirectedUrl());
}
};
}
/**
* Access to response status assertions.
*/
public static StatusResultMatchers status() {
return new StatusResultMatchers();
}
/**
* Access to response header assertions.
*/
public static HeaderResultMatchers header() {
return new HeaderResultMatchers();
}
/**
* Access to response body assertions.
*/
public static ContentResultMatchers content() {
return new ContentResultMatchers();
}
/**
* Access to response body assertions using a <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expression to
* inspect a specific subset of the body. The JSON path expression can be a
* parameterized string using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the JSON path optionally parameterized with arguments
* @param args arguments to parameterize the JSON path expression with
*/
public static JsonPathResultMatchers jsonPath(String expression, Object ... args) {
return new JsonPathResultMatchers(expression, args);
}
/**
* Access to response body assertions using a <a
* href="http://goessner.net/articles/JsonPath/">JSONPath</a> expression to
* inspect a specific subset of the body and a Hamcrest match for asserting
* the value found at the JSON path.
*
* @param expression the JSON path expression
* @param matcher a matcher for the value expected at the JSON path
*/
public static <T> ResultMatcher jsonPath(String expression, Matcher<T> matcher) {
return new JsonPathResultMatchers(expression).value(matcher);
}
/**
* Access to response body assertions using an XPath to inspect a specific
* subset of the body. The XPath expression can be a parameterized string
* using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the XPath optionally parameterized with arguments
* @param args arguments to parameterize the XPath expression with
*/
public static XpathResultMatchers xpath(String expression, Object... args) throws XPathExpressionException {
return new XpathResultMatchers(expression, null, args);
}
/**
* Access to response body assertions using an XPath to inspect a specific
* subset of the body. The XPath expression can be a parameterized string
* using formatting specifiers as defined in
* {@link String#format(String, Object...)}.
*
* @param expression the XPath optionally parameterized with arguments
* @param namespaces namespaces referenced in the XPath expression
* @param args arguments to parameterize the XPath expression with
*/
public static XpathResultMatchers xpath(String expression, Map<String, String> namespaces, Object... args)
throws XPathExpressionException {
return new XpathResultMatchers(expression, namespaces, args);
}
/**
* Access to response cookie assertions.
*/
public static CookieResultMatchers cookie() {
return new CookieResultMatchers();
}
}
/*
* Copyright 2002-2012 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.mock.servlet.result;
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.springframework.test.web.mock.servlet.MvcResult;
import org.springframework.test.web.mock.servlet.ResultMatcher;
import org.springframework.web.servlet.ModelAndView;
/**
* Factory for assertions on the selected view. An instance of this class is
* typically accessed via {@link MockMvcResultMatchers#view()}.
* @since 3.2
*/
public class ViewResultMatchers {
/**
* Protected constructor.
* Use {@link MockMvcResultMatchers#view()}.
*/
protected ViewResultMatchers() {
}
/**
* Assert the selected view name with the given Hamcrest {@link Matcher}.
*/
public ResultMatcher name(final Matcher<? super String> matcher) {
return new ResultMatcher() {
public void match(MvcResult result) throws Exception {
ModelAndView mav = result.getModelAndView();
assertTrue("No ModelAndView found", mav != null);
MatcherAssert.assertThat("View name", mav.getViewName(), matcher);
}
};
}
/**
* Assert the selected view name.
*/
public ResultMatcher name(final String name) {
return name(Matchers.equalTo(name));
}
}
/*
* Copyright 2002-2012 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.
*/
/**
* Contains built-in {@code ResultMatcher} and {@code ResultHandler} implementations.
* Use {@link org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers}
* and {@link org.springframework.test.web.mock.servlet.result.MockMvcResultHandlers}
* to access to instances of those implementations.
*/
package org.springframework.test.web.mock.servlet.result;
/*
* Copyright 2002-2012 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.
*/
/**
* Contains built-in {@code MockMvcBuilder} implementations.
* Use {@link org.springframework.test.web.mock.servlet.setup.MockMvcBuilders}
* to access to instances of those implementations.
*/
package org.springframework.test.web.mock.servlet.setup;
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册