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
This commit is contained in:
committed by
Rossen Stoyanchev
parent
4812c181d4
commit
22bcb54ab6
42
build.gradle
42
build.gradle
@@ -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 {
|
||||
|
||||
72
merge-dist.gradle
Normal file
72
merge-dist.gradle
Normal file
@@ -0,0 +1,72 @@
|
||||
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'
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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);
|
||||
* // 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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, "");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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) { }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* 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.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.springframework.beans.Mergeable;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.RequestBuilder;
|
||||
import org.springframework.test.web.mock.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
import org.springframework.web.servlet.support.SessionFlashMapManager;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Default builder for {@link MockHttpServletRequest} required as input to
|
||||
* perform request in {@link MockMvc}.
|
||||
*
|
||||
* <p>Application tests will typically access this builder through the static
|
||||
* factory methods in {@link MockMvcBuilders}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.2
|
||||
*/
|
||||
public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
private final UriComponentsBuilder uriComponentsBuilder;
|
||||
|
||||
private final HttpMethod method;
|
||||
|
||||
private final MultiValueMap<String, Object> headers = new LinkedMultiValueMap<String, Object>();
|
||||
|
||||
private String contentType;
|
||||
|
||||
private byte[] content;
|
||||
|
||||
private final MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
|
||||
|
||||
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
||||
|
||||
private Locale locale;
|
||||
|
||||
private String characterEncoding;
|
||||
|
||||
private Principal principal;
|
||||
|
||||
private Boolean secure;
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
private MockHttpSession session;
|
||||
|
||||
private final Map<String, Object> sessionAttributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
private final Map<String, Object> flashAttributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private String servletPath = "";
|
||||
|
||||
private String pathInfo = ValueConstants.DEFAULT_NONE;
|
||||
|
||||
private final List<RequestPostProcessor> postProcessors =
|
||||
new ArrayList<RequestPostProcessor>();
|
||||
|
||||
|
||||
/**
|
||||
* Package private constructor. To get an instance, use static factory
|
||||
* methods in {@link MockMvcRequestBuilders}.
|
||||
*
|
||||
* <p>Although this class cannot be extended, additional ways to initialize
|
||||
* the {@code MockHttpServletRequest} can be plugged in via
|
||||
* {@link #with(RequestPostProcessor)}.
|
||||
*
|
||||
* @param uri the URI for the request including any component (e.g. scheme, host, query)
|
||||
* @param httpMethod the HTTP method for the request
|
||||
*/
|
||||
MockHttpServletRequestBuilder(URI uri, HttpMethod httpMethod) {
|
||||
|
||||
Assert.notNull(uri, "uri is required");
|
||||
Assert.notNull(httpMethod, "httpMethod is required");
|
||||
|
||||
this.uriComponentsBuilder = UriComponentsBuilder.fromUri(uri);
|
||||
this.method = httpMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a request parameter to the {@link MockHttpServletRequest}.
|
||||
* If called more than once, the new values are added.
|
||||
*
|
||||
* @param name the parameter name
|
||||
* @param values one or more values
|
||||
*/
|
||||
public MockHttpServletRequestBuilder param(String name, String... values) {
|
||||
addToMultiValueMap(this.parameters, name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a header to the request. Values are always added.
|
||||
*
|
||||
* @param name the header name
|
||||
* @param values one or more header values
|
||||
*/
|
||||
public MockHttpServletRequestBuilder header(String name, Object... values) {
|
||||
addToMultiValueMap(this.headers, name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all headers to the request. Values are always added.
|
||||
*
|
||||
* @param httpHeaders the headers and values to add
|
||||
*/
|
||||
public MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders) {
|
||||
for (String name : httpHeaders.keySet()) {
|
||||
Object[] values = ObjectUtils.toObjectArray(httpHeaders.get(name).toArray());
|
||||
addToMultiValueMap(this.headers, name, values);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'Content-Type' header of the request.
|
||||
*
|
||||
* @param mediaType the content type
|
||||
*/
|
||||
public MockHttpServletRequestBuilder contentType(MediaType mediaType) {
|
||||
Assert.notNull(mediaType, "'contentType' must not be null");
|
||||
this.contentType = mediaType.toString();
|
||||
this.headers.set("Content-Type", this.contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'Accept' header to the given media type(s).
|
||||
*
|
||||
* @param mediaTypes one or more media types
|
||||
*/
|
||||
public MockHttpServletRequestBuilder accept(MediaType... mediaTypes) {
|
||||
Assert.notEmpty(mediaTypes, "No 'Accept' media types");
|
||||
this.headers.set("Accept", MediaType.toString(Arrays.asList(mediaTypes)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the request body.
|
||||
*
|
||||
* @param content the body content
|
||||
*/
|
||||
public MockHttpServletRequestBuilder body(byte[] content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given cookies to the request. Cookies are always added.
|
||||
*
|
||||
* @param cookies the cookies to add
|
||||
*/
|
||||
public MockHttpServletRequestBuilder cookie(Cookie... cookies) {
|
||||
Assert.notNull(cookies, "'cookies' must not be null");
|
||||
Assert.notEmpty(cookies, "'cookies' must not be empty");
|
||||
this.cookies.addAll(Arrays.asList(cookies));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locale of the request.
|
||||
*
|
||||
* @param locale the locale
|
||||
*/
|
||||
public MockHttpServletRequestBuilder locale(Locale locale) {
|
||||
this.locale = locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the character encoding of the request.
|
||||
*
|
||||
* @param encoding the character encoding
|
||||
*/
|
||||
public MockHttpServletRequestBuilder characterEncoding(String encoding) {
|
||||
this.characterEncoding = encoding;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a request attribute.
|
||||
*
|
||||
* @param name the attribute name
|
||||
* @param value the attribute value
|
||||
*/
|
||||
public MockHttpServletRequestBuilder requestAttr(String name, Object value) {
|
||||
addAttributeToMap(this.attributes, name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a session attribute.
|
||||
*
|
||||
* @param name the session attribute name
|
||||
* @param value the session attribute value
|
||||
*/
|
||||
public MockHttpServletRequestBuilder sessionAttr(String name, Object value) {
|
||||
addAttributeToMap(this.sessionAttributes, name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set session attributes.
|
||||
*
|
||||
* @param sessionAttributes the session attributes
|
||||
*/
|
||||
public MockHttpServletRequestBuilder sessionAttrs(Map<String, Object> sessionAttributes) {
|
||||
Assert.notEmpty(sessionAttributes, "'sessionAttrs' must not be empty");
|
||||
for (String name : sessionAttributes.keySet()) {
|
||||
sessionAttr(name, sessionAttributes.get(name));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an "input" flash attribute.
|
||||
*
|
||||
* @param name the flash attribute name
|
||||
* @param value the flash attribute value
|
||||
*/
|
||||
public MockHttpServletRequestBuilder flashAttr(String name, Object value) {
|
||||
addAttributeToMap(this.flashAttributes, name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flash attributes.
|
||||
*
|
||||
* @param flashAttributes the flash attributes
|
||||
*/
|
||||
public MockHttpServletRequestBuilder flashAttrs(Map<String, Object> flashAttributes) {
|
||||
Assert.notEmpty(flashAttributes, "'flashAttrs' must not be empty");
|
||||
for (String name : flashAttributes.keySet()) {
|
||||
flashAttr(name, flashAttributes.get(name));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTTP session to use, possibly re-used across requests.
|
||||
*
|
||||
* <p>Individual attributes provided via {@link #sessionAttr(String, Object)}
|
||||
* override the content of the session provided here.
|
||||
*
|
||||
* @param session the HTTP session
|
||||
*/
|
||||
public MockHttpServletRequestBuilder session(MockHttpSession session) {
|
||||
Assert.notNull(session, "'session' must not be null");
|
||||
this.session = session;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the principal of the request.
|
||||
*
|
||||
* @param principal the principal
|
||||
*/
|
||||
public MockHttpServletRequestBuilder principal(Principal principal) {
|
||||
Assert.notNull(principal, "'principal' must not be null");
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the portion of the requestURI that represents the context path.
|
||||
* The context path, if specified, must match to the start of the request
|
||||
* URI.
|
||||
*
|
||||
* <p>In most cases, tests can be written by omitting the context path from
|
||||
* the requestURI. This is because most applications don't actually depend
|
||||
* on the name under which they're deployed. If specified here, the context
|
||||
* path must start with a "/" and must not end with a "/".
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getContextPath%28%29">HttpServletRequest.getContextPath()</a>
|
||||
*/
|
||||
public MockHttpServletRequestBuilder contextPath(String contextPath) {
|
||||
if (StringUtils.hasText(contextPath)) {
|
||||
Assert.isTrue(contextPath.startsWith("/"), "Context path must start with a '/'");
|
||||
Assert.isTrue(!contextPath.endsWith("/"), "Context path must not end with a '/'");
|
||||
}
|
||||
this.contextPath = (contextPath != null) ? contextPath : "";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the portion of the requestURI that represents the path to which
|
||||
* the Servlet is mapped. This is typically a portion of the requestURI
|
||||
* after the context path.
|
||||
*
|
||||
* <p>In most cases, tests can be written by omitting the servlet path from
|
||||
* the requestURI. This is because most applications don't actually depend
|
||||
* on the prefix to which a servlet is mapped. For example if a Servlet is
|
||||
* mapped to {@code "/main/*"}, tests can be written with the requestURI
|
||||
* {@code "/accounts/1"} as opposed to {@code "/main/accounts/1"}.
|
||||
* If specified here, the servletPath must start with a "/" and must not
|
||||
* end with a "/".
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getServletPath%28%29">HttpServletRequest.getServletPath()</a>
|
||||
*/
|
||||
public MockHttpServletRequestBuilder servletPath(String servletPath) {
|
||||
if (StringUtils.hasText(servletPath)) {
|
||||
Assert.isTrue(servletPath.startsWith("/"), "Servlet path must start with a '/'");
|
||||
Assert.isTrue(!servletPath.endsWith("/"), "Servlet path must not end with a '/'");
|
||||
}
|
||||
this.servletPath = (servletPath != null) ? servletPath : "";
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the portion of the requestURI that represents the pathInfo.
|
||||
*
|
||||
* <p>If left unspecified (recommended), the pathInfo will be automatically
|
||||
* derived by removing the contextPath and the servletPath from the
|
||||
* requestURI and using any remaining part. If specified here, the pathInfo
|
||||
* must start with a "/".
|
||||
*
|
||||
* <p>If specified, the pathInfo will be used as is.
|
||||
*
|
||||
* @see <a
|
||||
* href="http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getPathInfo%28%29">HttpServletRequest.getServletPath()</a>
|
||||
*/
|
||||
public MockHttpServletRequestBuilder pathInfo(String pathInfo) {
|
||||
if (StringUtils.hasText(pathInfo)) {
|
||||
Assert.isTrue(pathInfo.startsWith("/"), "pathInfo must start with a '/'");
|
||||
}
|
||||
this.pathInfo = pathInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secure property of the {@link ServletRequest} indicating use of a
|
||||
* secure channel, such as HTTPS.
|
||||
*
|
||||
* @param secure whether the request is using a secure channel
|
||||
*/
|
||||
public MockHttpServletRequestBuilder secure(boolean secure){
|
||||
this.secure = secure;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension point for further initialization of {@link MockHttpServletRequest}
|
||||
* in ways not built directly into the {@code MockHttpServletRequestBuilder}.
|
||||
* Implementation of this interface can have builder-style methods themselves
|
||||
* and be made accessible through static factory methods.
|
||||
*
|
||||
* @param postProcessor a post-processor to add
|
||||
*/
|
||||
public MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor) {
|
||||
Assert.notNull(postProcessor, "postProcessor is required");
|
||||
this.postProcessors.add(postProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @return always returns {@code true}.
|
||||
*/
|
||||
public boolean isMergeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the properties of the "parent" RequestBuilder accepting values
|
||||
* only if not already set in "this" instance.
|
||||
*
|
||||
* @param parent the parent {@code RequestBuilder} to inherit properties from
|
||||
* @return the result of the merge
|
||||
*/
|
||||
public Object merge(Object parent) {
|
||||
if (parent == null) {
|
||||
return this;
|
||||
}
|
||||
if (!(parent instanceof MockHttpServletRequestBuilder)) {
|
||||
throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]");
|
||||
}
|
||||
|
||||
MockHttpServletRequestBuilder parentBuilder = (MockHttpServletRequestBuilder) parent;
|
||||
|
||||
for (String headerName : parentBuilder.headers.keySet()) {
|
||||
if (!this.headers.containsKey(headerName)) {
|
||||
this.headers.put(headerName, parentBuilder.headers.get(headerName));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.contentType == null) {
|
||||
this.contentType = parentBuilder.contentType;
|
||||
}
|
||||
|
||||
if (this.content == null) {
|
||||
this.content = parentBuilder.content;
|
||||
}
|
||||
|
||||
for (String paramName : parentBuilder.parameters.keySet()) {
|
||||
if (!this.parameters.containsKey(paramName)) {
|
||||
this.parameters.put(paramName, parentBuilder.parameters.get(paramName));
|
||||
}
|
||||
}
|
||||
|
||||
for (Cookie cookie : parentBuilder.cookies) {
|
||||
if (!containsCookie(cookie)) {
|
||||
this.cookies.add(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.locale == null) {
|
||||
this.locale = parentBuilder.locale;
|
||||
}
|
||||
|
||||
if (this.characterEncoding == null) {
|
||||
this.characterEncoding = parentBuilder.characterEncoding;
|
||||
}
|
||||
|
||||
if (this.principal == null) {
|
||||
this.principal = parentBuilder.principal;
|
||||
}
|
||||
|
||||
if (this.secure == null) {
|
||||
this.secure = parentBuilder.secure;
|
||||
}
|
||||
|
||||
for (String attributeName : parentBuilder.attributes.keySet()) {
|
||||
if (!this.attributes.containsKey(attributeName)) {
|
||||
this.attributes.put(attributeName, parentBuilder.attributes.get(attributeName));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.session == null) {
|
||||
this.session = parentBuilder.session;
|
||||
}
|
||||
|
||||
for (String sessionAttributeName : parentBuilder.sessionAttributes.keySet()) {
|
||||
if (!this.sessionAttributes.containsKey(sessionAttributeName)) {
|
||||
this.sessionAttributes.put(sessionAttributeName, parentBuilder.sessionAttributes.get(sessionAttributeName));
|
||||
}
|
||||
}
|
||||
|
||||
for (String flashAttributeName : parentBuilder.flashAttributes.keySet()) {
|
||||
if (!this.flashAttributes.containsKey(flashAttributeName)) {
|
||||
this.flashAttributes.put(flashAttributeName, parentBuilder.flashAttributes.get(flashAttributeName));
|
||||
}
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(this.contextPath)) {
|
||||
this.contextPath = parentBuilder.contextPath;
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(this.servletPath)) {
|
||||
this.servletPath = parentBuilder.servletPath;
|
||||
}
|
||||
|
||||
if (ValueConstants.DEFAULT_NONE.equals(this.pathInfo)) {
|
||||
this.pathInfo = parentBuilder.pathInfo;
|
||||
}
|
||||
|
||||
this.postProcessors.addAll(parentBuilder.postProcessors);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean containsCookie(Cookie cookie) {
|
||||
for (Cookie c : this.cookies) {
|
||||
if (ObjectUtils.nullSafeEquals(c.getName(), cookie.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link MockHttpServletRequest}.
|
||||
*/
|
||||
public final MockHttpServletRequest buildRequest(ServletContext servletContext) {
|
||||
|
||||
MockHttpServletRequest request = createServletRequest(servletContext);
|
||||
|
||||
UriComponents uriComponents = this.uriComponentsBuilder.build();
|
||||
|
||||
String requestUri = uriComponents.getPath();
|
||||
request.setRequestURI(requestUri);
|
||||
|
||||
updatePathRequestProperties(request, requestUri);
|
||||
|
||||
if (uriComponents.getScheme() != null) {
|
||||
request.setScheme(uriComponents.getScheme());
|
||||
}
|
||||
if (uriComponents.getHost() != null) {
|
||||
request.setServerName(uriComponents.getHost());
|
||||
}
|
||||
if (uriComponents.getPort() != -1) {
|
||||
request.setServerPort(uriComponents.getPort());
|
||||
}
|
||||
|
||||
request.setMethod(this.method.name());
|
||||
|
||||
for (String name : this.headers.keySet()) {
|
||||
for (Object value : this.headers.get(name)) {
|
||||
request.addHeader(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
request.setQueryString(uriComponents.getQuery());
|
||||
|
||||
for (Entry<String, List<String>> entry : uriComponents.getQueryParams().entrySet()) {
|
||||
for (String value : entry.getValue()) {
|
||||
request.addParameter(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
|
||||
for (String name : this.parameters.keySet()) {
|
||||
for (String value : this.parameters.get(name)) {
|
||||
request.addParameter(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
request.setContentType(this.contentType);
|
||||
request.setContent(this.content);
|
||||
|
||||
request.setCookies(this.cookies.toArray(new Cookie[this.cookies.size()]));
|
||||
|
||||
if (this.locale != null) {
|
||||
request.addPreferredLocale(this.locale);
|
||||
}
|
||||
|
||||
request.setCharacterEncoding(this.characterEncoding);
|
||||
|
||||
request.setUserPrincipal(this.principal);
|
||||
|
||||
if (this.secure != null) {
|
||||
request.setSecure(this.secure);
|
||||
}
|
||||
|
||||
for (String name : this.attributes.keySet()) {
|
||||
request.setAttribute(name, this.attributes.get(name));
|
||||
}
|
||||
|
||||
// Set session before session and flash attributes
|
||||
|
||||
if (this.session != null) {
|
||||
request.setSession(this.session);
|
||||
}
|
||||
|
||||
for (String name : this.sessionAttributes.keySet()) {
|
||||
request.getSession().setAttribute(name, this.sessionAttributes.get(name));
|
||||
}
|
||||
|
||||
FlashMap flashMap = new FlashMap();
|
||||
flashMap.putAll(this.flashAttributes);
|
||||
|
||||
FlashMapManager flashMapManager = getFlashMapManager(request);
|
||||
flashMapManager.saveOutputFlashMap(flashMap, request, new MockHttpServletResponse());
|
||||
|
||||
// Apply post-processors at the very end
|
||||
|
||||
for (RequestPostProcessor postProcessor : this.postProcessors) {
|
||||
request = postProcessor.postProcessRequest(request);
|
||||
Assert.notNull(request, "Post-processor [" + postProcessor.getClass().getName() + "] returned null");
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MockHttpServletRequest} based on the given
|
||||
* {@link ServletContext}. Can be overridden in sub-classes.
|
||||
*/
|
||||
protected MockHttpServletRequest createServletRequest(ServletContext servletContext) {
|
||||
return ClassUtils.hasMethod(ServletRequest.class, "startAsync") ?
|
||||
createServlet3Request(servletContext) : new MockHttpServletRequest(servletContext);
|
||||
}
|
||||
|
||||
private static MockHttpServletRequest createServlet3Request(ServletContext servletContext) {
|
||||
try {
|
||||
String className = "org.springframework.test.web.mock.servlet.request.Servlet3MockHttpServletRequest";
|
||||
Class<?> clazz = ClassUtils.forName(className, MockHttpServletRequestBuilder.class.getClassLoader());
|
||||
Constructor<?> constructor = clazz.getConstructor(ServletContext.class);
|
||||
return (MockHttpServletRequest) BeanUtils.instantiateClass(constructor, servletContext);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw new IllegalStateException("Failed to instantiate MockHttpServletRequest", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the contextPath, servletPath, and pathInfo of the request.
|
||||
*/
|
||||
private void updatePathRequestProperties(MockHttpServletRequest request, String requestUri) {
|
||||
|
||||
Assert.isTrue(requestUri.startsWith(this.contextPath),
|
||||
"requestURI [" + requestUri + "] does not start with contextPath [" + this.contextPath + "]");
|
||||
|
||||
request.setContextPath(this.contextPath);
|
||||
request.setServletPath(this.servletPath);
|
||||
|
||||
if (ValueConstants.DEFAULT_NONE.equals(this.pathInfo)) {
|
||||
|
||||
Assert.isTrue(requestUri.startsWith(this.contextPath + this.servletPath),
|
||||
"Invalid servletPath [" + this.servletPath + "] for requestURI [" + requestUri + "]");
|
||||
|
||||
String extraPath = requestUri.substring(this.contextPath.length() + this.servletPath.length());
|
||||
this.pathInfo = (StringUtils.hasText(extraPath)) ? extraPath : null;
|
||||
}
|
||||
|
||||
request.setPathInfo(this.pathInfo);
|
||||
}
|
||||
|
||||
private FlashMapManager getFlashMapManager(MockHttpServletRequest request) {
|
||||
FlashMapManager flashMapManager = null;
|
||||
try {
|
||||
ServletContext servletContext = request.getServletContext();
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
|
||||
flashMapManager = wac.getBean(DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
}
|
||||
return (flashMapManager != null) ? flashMapManager : new SessionFlashMapManager();
|
||||
}
|
||||
|
||||
private static <T> void addToMultiValueMap(MultiValueMap<String, T> map, String name, T[] values) {
|
||||
Assert.hasLength(name, "'name' must not be empty");
|
||||
Assert.notNull(values, "'values' is required");
|
||||
Assert.notEmpty(values, "'values' must not be empty");
|
||||
for (T value : values) {
|
||||
map.add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addAttributeToMap(Map<String, Object> map, String name, Object value) {
|
||||
Assert.hasLength(name, "'name' must not be empty");
|
||||
Assert.notNull(value, "'value' must not be null");
|
||||
map.put(name, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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 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.validation.BindingResult;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Factory for assertions on the model. An instance of this class is
|
||||
* typically accessed via {@link MockMvcResultMatchers#model()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class ModelResultMatchers {
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor.
|
||||
* Use {@link MockMvcResultMatchers#model()}.
|
||||
*/
|
||||
protected ModelResultMatchers() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a model attribute 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 {
|
||||
ModelAndView mav = result.getModelAndView();
|
||||
assertTrue("No ModelAndView found", mav != null);
|
||||
MatcherAssert.assertThat("Model attribute '" + name + "'", (T) mav.getModel().get(name), matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a model attribute value.
|
||||
*/
|
||||
public ResultMatcher attribute(String name, Object value) {
|
||||
return attribute(name, Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the given model attributes exist.
|
||||
*/
|
||||
public ResultMatcher attributeExists(final String... names) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
assertTrue("No ModelAndView found", result.getModelAndView() != null);
|
||||
for (String name : names) {
|
||||
attribute(name, Matchers.notNullValue()).match(result);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the given model attribute(s) have errors.
|
||||
*/
|
||||
public ResultMatcher attributeHasErrors(final String... names) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult mvcResult) throws Exception {
|
||||
ModelAndView mav = getModelAndView(mvcResult);
|
||||
for (String name : names) {
|
||||
BindingResult result = getBindingResult(mav, name);
|
||||
assertTrue("No errors for attribute: " + name, result.hasErrors());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the given model attribute(s) do not have errors.
|
||||
*/
|
||||
public ResultMatcher attributeHasNoErrors(final String... names) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult mvcResult) throws Exception {
|
||||
ModelAndView mav = getModelAndView(mvcResult);
|
||||
for (String name : names) {
|
||||
BindingResult result = getBindingResult(mav, name);
|
||||
assertTrue("No errors for attribute: " + name, !result.hasErrors());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the given model attribute field(s) have errors.
|
||||
*/
|
||||
public ResultMatcher attributeHasFieldErrors(final String name, final String... fieldNames) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult mvcResult) throws Exception {
|
||||
ModelAndView mav = getModelAndView(mvcResult);
|
||||
BindingResult result = getBindingResult(mav, name);
|
||||
assertTrue("No errors for attribute: '" + name + "'", result.hasErrors());
|
||||
for (final String fieldName : fieldNames) {
|
||||
assertTrue("No errors for field: '" + fieldName + "' of attribute: " + name,
|
||||
result.hasFieldErrors(fieldName));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the model has no errors.
|
||||
*/
|
||||
public <T> ResultMatcher hasNoErrors() {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
ModelAndView mav = getModelAndView(result);
|
||||
for (Object value : mav.getModel().values()) {
|
||||
if (value instanceof BindingResult) {
|
||||
assertTrue("Unexpected binding error(s): " + value, !((BindingResult) value).hasErrors());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the number of model attributes.
|
||||
*/
|
||||
public <T> ResultMatcher size(final int size) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
ModelAndView mav = getModelAndView(result);
|
||||
int actual = 0;
|
||||
for (String key : mav.getModel().keySet()) {
|
||||
if (!key.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
|
||||
actual++;
|
||||
}
|
||||
}
|
||||
assertEquals("Model size", size, actual);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ModelAndView getModelAndView(MvcResult mvcResult) {
|
||||
ModelAndView mav = mvcResult.getModelAndView();
|
||||
assertTrue("No ModelAndView found", mav != null);
|
||||
return mav;
|
||||
}
|
||||
|
||||
private BindingResult getBindingResult(ModelAndView mav, String name) {
|
||||
BindingResult result = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);
|
||||
assertTrue("No BindingResult for attribute: " + name, result != null);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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 java.util.Enumeration;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultHandler;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Result handler that prints {@link MvcResult} details to the "standard" output
|
||||
* stream. An instance of this class is typically accessed via
|
||||
* {@link MockMvcResultHandlers#print()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class PrintingResultHandler implements ResultHandler {
|
||||
|
||||
private final ResultValuePrinter printer;
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor.
|
||||
* @param printer a {@link ResultValuePrinter} to do the actual writing
|
||||
*/
|
||||
protected PrintingResultHandler(ResultValuePrinter printer) {
|
||||
this.printer = printer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the result value printer.
|
||||
*/
|
||||
protected ResultValuePrinter getPrinter() {
|
||||
return this.printer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print {@link MvcResult} details to the "standard" output stream.
|
||||
*/
|
||||
public final void handle(MvcResult result) throws Exception {
|
||||
|
||||
this.printer.printHeading("MockHttpServletRequest");
|
||||
printRequest(result.getRequest());
|
||||
|
||||
this.printer.printHeading("Handler");
|
||||
printHandler(result.getHandler(), result.getInterceptors());
|
||||
|
||||
this.printer.printHeading("Resolved Exception");
|
||||
printResolvedException(result.getResolvedException());
|
||||
|
||||
this.printer.printHeading("ModelAndView");
|
||||
printModelAndView(result.getModelAndView());
|
||||
|
||||
this.printer.printHeading("FlashMap");
|
||||
printFlashMap(RequestContextUtils.getOutputFlashMap(result.getRequest()));
|
||||
|
||||
this.printer.printHeading("MockHttpServletResponse");
|
||||
printResponse(result.getResponse());
|
||||
}
|
||||
|
||||
/** Print the request */
|
||||
protected void printRequest(MockHttpServletRequest request) throws Exception {
|
||||
this.printer.printValue("HTTP Method", request.getMethod());
|
||||
this.printer.printValue("Request URI", request.getRequestURI());
|
||||
this.printer.printValue("Parameters", request.getParameterMap());
|
||||
this.printer.printValue("Headers", getRequestHeaders(request));
|
||||
}
|
||||
|
||||
protected static HttpHeaders getRequestHeaders(MockHttpServletRequest request) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Enumeration<?> names = request.getHeaderNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = (String) names.nextElement();
|
||||
Enumeration<String> values = request.getHeaders(name);
|
||||
while (values.hasMoreElements()) {
|
||||
headers.add(name, values.nextElement());
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
/** Print the handler */
|
||||
protected void printHandler(Object handler, HandlerInterceptor[] interceptors) throws Exception {
|
||||
if (handler == null) {
|
||||
this.printer.printValue("Type", null);
|
||||
}
|
||||
else {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
this.printer.printValue("Type", handlerMethod.getBeanType().getName());
|
||||
this.printer.printValue("Method", handlerMethod);
|
||||
}
|
||||
else {
|
||||
this.printer.printValue("Type", handler.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Print exceptions resolved through a HandlerExceptionResolver */
|
||||
protected void printResolvedException(Exception resolvedException) throws Exception {
|
||||
if (resolvedException == null) {
|
||||
this.printer.printValue("Type", null);
|
||||
}
|
||||
else {
|
||||
this.printer.printValue("Type", resolvedException.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
/** Print the ModelAndView */
|
||||
protected void printModelAndView(ModelAndView mav) throws Exception {
|
||||
this.printer.printValue("View name", (mav != null) ? mav.getViewName() : null);
|
||||
this.printer.printValue("View", (mav != null) ? mav.getView() : null);
|
||||
if (mav == null || mav.getModel().size() == 0) {
|
||||
this.printer.printValue("Model", null);
|
||||
}
|
||||
else {
|
||||
for (String name : mav.getModel().keySet()) {
|
||||
if (!name.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
|
||||
Object value = mav.getModel().get(name);
|
||||
this.printer.printValue("Attribute", name);
|
||||
this.printer.printValue("value", value);
|
||||
Errors errors = (Errors) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);
|
||||
if (errors != null) {
|
||||
this.printer.printValue("errors", errors.getAllErrors());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Print "output" flash attributes */
|
||||
protected void printFlashMap(FlashMap flashMap) throws Exception {
|
||||
if (flashMap == null) {
|
||||
this.printer.printValue("Attributes", null);
|
||||
}
|
||||
else {
|
||||
for (String name : flashMap.keySet()) {
|
||||
this.printer.printValue("Attribute", name);
|
||||
this.printer.printValue("value", flashMap.get(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Print the response */
|
||||
protected void printResponse(MockHttpServletResponse response) throws Exception {
|
||||
this.printer.printValue("Status", response.getStatus());
|
||||
this.printer.printValue("Error message", response.getErrorMessage());
|
||||
this.printer.printValue("Headers", getResponseHeaders(response));
|
||||
this.printer.printValue("Content type", response.getContentType());
|
||||
this.printer.printValue("Body", response.getContentAsString());
|
||||
this.printer.printValue("Forwarded URL", response.getForwardedUrl());
|
||||
this.printer.printValue("Redirected URL", response.getRedirectedUrl());
|
||||
this.printer.printValue("Cookies", response.getCookies());
|
||||
}
|
||||
|
||||
protected static HttpHeaders getResponseHeaders(MockHttpServletResponse response) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
for (String name : response.getHeaderNames()) {
|
||||
headers.put(name, response.getHeaders(name));
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A contract for how to actually write result information.
|
||||
*/
|
||||
protected interface ResultValuePrinter {
|
||||
|
||||
void printHeading(String heading);
|
||||
|
||||
void printValue(String label, Object value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 java.util.concurrent.Callable;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
import org.springframework.web.context.request.async.AsyncTask;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.context.request.async.WebAsyncManager;
|
||||
import org.springframework.web.context.request.async.WebAsyncUtils;
|
||||
|
||||
/**
|
||||
* Factory for assertions on the request. An instance of this class is
|
||||
* typically accessed via {@link MockMvcResultMatchers#request()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class RequestResultMatchers {
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor.
|
||||
* Use {@link MockMvcResultMatchers#request()}.
|
||||
*/
|
||||
protected RequestResultMatchers() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a request attribute value with the given Hamcrest {@link Matcher}.
|
||||
* Whether asynchronous processing started, usually as a result of a
|
||||
* controller method returning {@link Callable} or {@link DeferredResult}.
|
||||
* The test will await the completion of a {@code Callable} so that
|
||||
* {@link #asyncResult(Matcher)} can be used to assert the resulting value.
|
||||
* Neither a {@code Callable} nor a {@code DeferredResult} will complete
|
||||
* processing all the way since a {@link MockHttpServletRequest} does not
|
||||
* perform asynchronous dispatches.
|
||||
*/
|
||||
public ResultMatcher asyncStarted() {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) {
|
||||
HttpServletRequest request = result.getRequest();
|
||||
MatcherAssert.assertThat("Async started", request.isAsyncStarted(), equalTo(true));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that asynchronous processing was not start.
|
||||
* @see #asyncStarted()
|
||||
*/
|
||||
public ResultMatcher asyncNotStarted() {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) {
|
||||
HttpServletRequest request = result.getRequest();
|
||||
MatcherAssert.assertThat("Async started", request.isAsyncStarted(), equalTo(false));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the result from asynchronous processing with the given matcher.
|
||||
* This method can be used when a controller method returns {@link Callable}
|
||||
* or {@link AsyncTask}. The value matched is the value returned from the
|
||||
* {@code Callable} or the exception raised.
|
||||
*/
|
||||
public <T> ResultMatcher asyncResult(final Matcher<T> matcher) {
|
||||
return new ResultMatcher() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void match(MvcResult result) {
|
||||
HttpServletRequest request = result.getRequest();
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
MatcherAssert.assertThat("Async started", request.isAsyncStarted(), equalTo(true));
|
||||
MatcherAssert.assertThat("Callable result", (T) asyncManager.getConcurrentResult(), matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the result from asynchronous processing.
|
||||
* This method can be used when a controller method returns {@link Callable}
|
||||
* or {@link AsyncTask}. The value matched is the value returned from the
|
||||
* {@code Callable} or the exception raised.
|
||||
*/
|
||||
public <T> ResultMatcher asyncResult(Object expectedResult) {
|
||||
return asyncResult(equalTo(expectedResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a request attribute 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) {
|
||||
T value = (T) result.getRequest().getAttribute(name);
|
||||
MatcherAssert.assertThat("Request attribute: ", value, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a request attribute value.
|
||||
*/
|
||||
public <T> ResultMatcher attribute(String name, Object value) {
|
||||
return attribute(name, Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a session attribute value with the given Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public <T> ResultMatcher sessionAttribute(final String name, final Matcher<T> matcher) {
|
||||
return new ResultMatcher() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void match(MvcResult result) {
|
||||
T value = (T) result.getRequest().getSession().getAttribute(name);
|
||||
MatcherAssert.assertThat("Request attribute: ", value, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a session attribute value..
|
||||
*/
|
||||
public <T> ResultMatcher sessionAttribute(String name, Object value) {
|
||||
return sessionAttribute(name, Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* 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.http.HttpStatus;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
|
||||
/**
|
||||
* Factory for assertions on the response status. An instance of this class is
|
||||
* typically accessed via {@link MockMvcResultMatchers#status()}.
|
||||
*
|
||||
* @author Keesun Baik
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class StatusResultMatchers {
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor.
|
||||
* Use {@link MockMvcResultMatchers#status()}.
|
||||
*/
|
||||
protected StatusResultMatchers() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code with the given Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher is(final Matcher<Integer> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
MatcherAssert.assertThat("Status: ", result.getResponse().getStatus(), matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is equal to an integer value.
|
||||
*/
|
||||
public ResultMatcher is(int status) {
|
||||
return is(Matchers.equalTo(status));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert the Servlet response error message with the given Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher reason(final Matcher<? super String> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
MatcherAssert.assertThat("Status reason: ", result.getResponse().getErrorMessage(), matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the Servlet response error message.
|
||||
*/
|
||||
public ResultMatcher reason(String reason) {
|
||||
return reason(Matchers.equalTo(reason));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.CONTINUE} (100).
|
||||
*/
|
||||
public ResultMatcher isContinue() {
|
||||
return matcher(HttpStatus.CONTINUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.SWITCHING_PROTOCOLS} (101).
|
||||
*/
|
||||
public ResultMatcher isSwitchingProtocols() {
|
||||
return matcher(HttpStatus.SWITCHING_PROTOCOLS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PROCESSING} (102).
|
||||
*/
|
||||
public ResultMatcher isProcessing() {
|
||||
return matcher(HttpStatus.PROCESSING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.CHECKPOINT} (103).
|
||||
*/
|
||||
public ResultMatcher isCheckpoint() {
|
||||
return matcher(HttpStatus.valueOf(103));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.OK} (200).
|
||||
*/
|
||||
public ResultMatcher isOk() {
|
||||
return matcher(HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.CREATED} (201).
|
||||
*/
|
||||
public ResultMatcher isCreated() {
|
||||
return matcher(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.ACCEPTED} (202).
|
||||
*/
|
||||
public ResultMatcher isAccepted() {
|
||||
return matcher(HttpStatus.ACCEPTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NON_AUTHORITATIVE_INFORMATION} (203).
|
||||
*/
|
||||
public ResultMatcher isNonAuthoritativeInformation() {
|
||||
return matcher(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NO_CONTENT} (204).
|
||||
*/
|
||||
public ResultMatcher isNoContent() {
|
||||
return matcher(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.RESET_CONTENT} (205).
|
||||
*/
|
||||
public ResultMatcher isResetContent() {
|
||||
return matcher(HttpStatus.RESET_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PARTIAL_CONTENT} (206).
|
||||
*/
|
||||
public ResultMatcher isPartialContent() {
|
||||
return matcher(HttpStatus.PARTIAL_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.MULTI_STATUS} (207).
|
||||
*/
|
||||
public ResultMatcher isMultiStatus() {
|
||||
return matcher(HttpStatus.MULTI_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.ALREADY_REPORTED} (208).
|
||||
*/
|
||||
public ResultMatcher isAlreadyReported() {
|
||||
return matcher(HttpStatus.ALREADY_REPORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.IM_USED} (226).
|
||||
*/
|
||||
public ResultMatcher isImUsed() {
|
||||
return matcher(HttpStatus.IM_USED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.MULTIPLE_CHOICES} (300).
|
||||
*/
|
||||
public ResultMatcher isMultipleChoices() {
|
||||
return matcher(HttpStatus.MULTIPLE_CHOICES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.MOVED_PERMANENTLY} (301).
|
||||
*/
|
||||
public ResultMatcher isMovedPermanently() {
|
||||
return matcher(HttpStatus.MOVED_PERMANENTLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.FOUND} (302).
|
||||
*/
|
||||
public ResultMatcher isFound() {
|
||||
return matcher(HttpStatus.FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.MOVED_TEMPORARILY} (302).
|
||||
*/
|
||||
public ResultMatcher isMovedTemporarily() {
|
||||
return matcher(HttpStatus.MOVED_TEMPORARILY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.SEE_OTHER} (303).
|
||||
*/
|
||||
public ResultMatcher isSeeOther() {
|
||||
return matcher(HttpStatus.SEE_OTHER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NOT_MODIFIED} (304).
|
||||
*/
|
||||
public ResultMatcher isNotModified() {
|
||||
return matcher(HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.USE_PROXY} (305).
|
||||
*/
|
||||
public ResultMatcher isUseProxy() {
|
||||
return matcher(HttpStatus.USE_PROXY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.TEMPORARY_REDIRECT} (307).
|
||||
*/
|
||||
public ResultMatcher isTemporaryRedirect() {
|
||||
return matcher(HttpStatus.TEMPORARY_REDIRECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.RESUME_INCOMPLETE} (308).
|
||||
*/
|
||||
public ResultMatcher isResumeIncomplete() {
|
||||
return matcher(HttpStatus.valueOf(308));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.BAD_REQUEST} (400).
|
||||
*/
|
||||
public ResultMatcher isBadRequest() {
|
||||
return matcher(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.UNAUTHORIZED} (401).
|
||||
*/
|
||||
public ResultMatcher isUnauthorized() {
|
||||
return matcher(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PAYMENT_REQUIRED} (402).
|
||||
*/
|
||||
public ResultMatcher isPaymentRequired() {
|
||||
return matcher(HttpStatus.PAYMENT_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.FORBIDDEN} (403).
|
||||
*/
|
||||
public ResultMatcher isForbidden() {
|
||||
return matcher(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NOT_FOUND} (404).
|
||||
*/
|
||||
public ResultMatcher isNotFound() {
|
||||
return matcher(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.METHOD_NOT_ALLOWED} (405).
|
||||
*/
|
||||
public ResultMatcher isMethodNotAllowed() {
|
||||
return matcher(HttpStatus.METHOD_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NOT_ACCEPTABLE} (406).
|
||||
*/
|
||||
public ResultMatcher isNotAcceptable() {
|
||||
return matcher(HttpStatus.NOT_ACCEPTABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PROXY_AUTHENTICATION_REQUIRED} (407).
|
||||
*/
|
||||
public ResultMatcher isProxyAuthenticationRequired() {
|
||||
return matcher(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.REQUEST_TIMEOUT} (408).
|
||||
*/
|
||||
public ResultMatcher isRequestTimeout() {
|
||||
return matcher(HttpStatus.REQUEST_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.CONFLICT} (409).
|
||||
*/
|
||||
public ResultMatcher isConflict() {
|
||||
return matcher(HttpStatus.CONFLICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.GONE} (410).
|
||||
*/
|
||||
public ResultMatcher isGone() {
|
||||
return matcher(HttpStatus.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.LENGTH_REQUIRED} (411).
|
||||
*/
|
||||
public ResultMatcher isLengthRequired() {
|
||||
return matcher(HttpStatus.LENGTH_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PRECONDITION_FAILED} (412).
|
||||
*/
|
||||
public ResultMatcher isPreconditionFailed() {
|
||||
return matcher(HttpStatus.PRECONDITION_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.REQUEST_ENTITY_TOO_LARGE} (413).
|
||||
*/
|
||||
public ResultMatcher isRequestEntityTooLarge() {
|
||||
return matcher(HttpStatus.REQUEST_ENTITY_TOO_LARGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.REQUEST_URI_TOO_LONG} (414).
|
||||
*/
|
||||
public ResultMatcher isRequestUriTooLong() {
|
||||
return matcher(HttpStatus.REQUEST_URI_TOO_LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.UNSUPPORTED_MEDIA_TYPE} (415).
|
||||
*/
|
||||
public ResultMatcher isUnsupportedMediaType() {
|
||||
return matcher(HttpStatus.UNSUPPORTED_MEDIA_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE} (416).
|
||||
*/
|
||||
public ResultMatcher isRequestedRangeNotSatisfiable() {
|
||||
return matcher(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.EXPECTATION_FAILED} (417).
|
||||
*/
|
||||
public ResultMatcher isExpectationFailed() {
|
||||
return matcher(HttpStatus.EXPECTATION_FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.I_AM_A_TEAPOT} (418).
|
||||
*/
|
||||
public ResultMatcher isIAmATeapot() {
|
||||
return matcher(HttpStatus.valueOf(418));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE} (419).
|
||||
* @deprecated matching the deprecation of HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE
|
||||
*/
|
||||
public ResultMatcher isInsufficientSpaceOnResource() {
|
||||
return matcher(HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.METHOD_FAILURE} (420).
|
||||
* @deprecated matching the deprecation of HttpStatus.METHOD_FAILURE
|
||||
*/
|
||||
public ResultMatcher isMethodFailure() {
|
||||
return matcher(HttpStatus.METHOD_FAILURE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.DESTINATION_LOCKED} (421).
|
||||
* @deprecated matching the deprecation of HttpStatus.DESTINATION_LOCKED
|
||||
*/
|
||||
public ResultMatcher isDestinationLocked() {
|
||||
return matcher(HttpStatus.DESTINATION_LOCKED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.UNPROCESSABLE_ENTITY} (422).
|
||||
*/
|
||||
public ResultMatcher isUnprocessableEntity() {
|
||||
return matcher(HttpStatus.UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.LOCKED} (423).
|
||||
*/
|
||||
public ResultMatcher isLocked() {
|
||||
return matcher(HttpStatus.LOCKED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.FAILED_DEPENDENCY} (424).
|
||||
*/
|
||||
public ResultMatcher isFailedDependency() {
|
||||
return matcher(HttpStatus.FAILED_DEPENDENCY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.UPGRADE_REQUIRED} (426).
|
||||
*/
|
||||
public ResultMatcher isUpgradeRequired() {
|
||||
return matcher(HttpStatus.UPGRADE_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.PRECONDITION_REQUIRED} (428).
|
||||
*/
|
||||
public ResultMatcher isPreconditionRequired() {
|
||||
return matcher(HttpStatus.valueOf(428));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.TOO_MANY_REQUESTS} (429).
|
||||
*/
|
||||
public ResultMatcher isTooManyRequests() {
|
||||
return matcher(HttpStatus.valueOf(429));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE} (431).
|
||||
*/
|
||||
public ResultMatcher isRequestHeaderFieldsTooLarge() {
|
||||
return matcher(HttpStatus.valueOf(431));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.INTERNAL_SERVER_ERROR} (500).
|
||||
*/
|
||||
public ResultMatcher isInternalServerError() {
|
||||
return matcher(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NOT_IMPLEMENTED} (501).
|
||||
*/
|
||||
public ResultMatcher isNotImplemented() {
|
||||
return matcher(HttpStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.BAD_GATEWAY} (502).
|
||||
*/
|
||||
public ResultMatcher isBadGateway() {
|
||||
return matcher(HttpStatus.BAD_GATEWAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.SERVICE_UNAVAILABLE} (503).
|
||||
*/
|
||||
public ResultMatcher isServiceUnavailable() {
|
||||
return matcher(HttpStatus.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.GATEWAY_TIMEOUT} (504).
|
||||
*/
|
||||
public ResultMatcher isGatewayTimeout() {
|
||||
return matcher(HttpStatus.GATEWAY_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.HTTP_VERSION_NOT_SUPPORTED} (505).
|
||||
*/
|
||||
public ResultMatcher isHttpVersionNotSupported() {
|
||||
return matcher(HttpStatus.HTTP_VERSION_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.VARIANT_ALSO_NEGOTIATES} (506).
|
||||
*/
|
||||
public ResultMatcher isVariantAlsoNegotiates() {
|
||||
return matcher(HttpStatus.VARIANT_ALSO_NEGOTIATES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.INSUFFICIENT_STORAGE} (507).
|
||||
*/
|
||||
public ResultMatcher isInsufficientStorage() {
|
||||
return matcher(HttpStatus.INSUFFICIENT_STORAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.LOOP_DETECTED} (508).
|
||||
*/
|
||||
public ResultMatcher isLoopDetected() {
|
||||
return matcher(HttpStatus.LOOP_DETECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.BANDWIDTH_LIMIT_EXCEEDED} (509).
|
||||
*/
|
||||
public ResultMatcher isBandwidthLimitExceeded() {
|
||||
return matcher(HttpStatus.valueOf(509));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NOT_EXTENDED} (510).
|
||||
*/
|
||||
public ResultMatcher isNotExtended() {
|
||||
return matcher(HttpStatus.NOT_EXTENDED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the response status code is {@code HttpStatus.NETWORK_AUTHENTICATION_REQUIRED} (511).
|
||||
*/
|
||||
public ResultMatcher isNetworkAuthenticationRequired() {
|
||||
return matcher(HttpStatus.valueOf(511));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the expected response status to that of the HttpServletResponse
|
||||
*/
|
||||
private ResultMatcher matcher(final HttpStatus status) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) {
|
||||
assertEquals("Status", status.value(), result.getResponse().getStatus());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.mock.support.XpathExpectationsHelper;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Factory for response content {@code ResultMatcher}'s using an XPath
|
||||
* expression. An instance of this class is typically accessed via
|
||||
* {@link MockMvcResultMatchers#xpath}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class XpathResultMatchers {
|
||||
|
||||
private final XpathExpectationsHelper xpathHelper;
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor, not for direct instantiation. Use
|
||||
* {@link MockMvcResultMatchers#xpath(String, Object...)} or
|
||||
* {@link MockMvcResultMatchers#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 XpathResultMatchers(String expression, Map<String, String> namespaces, Object ... args)
|
||||
throws XPathExpressionException {
|
||||
|
||||
this.xpathHelper = new XpathExpectationsHelper(expression, namespaces, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the {@link Node} content found with the
|
||||
* given Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher node(final Matcher<? super Node> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
String content = result.getResponse().getContentAsString();
|
||||
xpathHelper.assertNode(content, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert that content exists.
|
||||
*/
|
||||
public ResultMatcher exists() {
|
||||
return node(Matchers.notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert that content doesn't exist.
|
||||
*/
|
||||
public ResultMatcher doesNotExist() {
|
||||
return node(Matchers.nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the number of nodes found with the given
|
||||
* Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher nodeCount(final Matcher<Integer> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
String content = result.getResponse().getContentAsString();
|
||||
xpathHelper.assertNodeCount(content, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the number of nodes found.
|
||||
*/
|
||||
public ResultMatcher nodeCount(int count) {
|
||||
return nodeCount(Matchers.equalTo(count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath and assert the {@link String} value found with the given
|
||||
* Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher string(final Matcher<? super String> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
String content = result.getResponse().getContentAsString();
|
||||
xpathHelper.assertString(content, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath and assert the {@link String} value found.
|
||||
*/
|
||||
public ResultMatcher string(String value) {
|
||||
return string(Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the {@link Double} value found with the
|
||||
* given Hamcrest {@link Matcher}.
|
||||
*/
|
||||
public ResultMatcher number(final Matcher<? super Double> matcher) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
String content = result.getResponse().getContentAsString();
|
||||
xpathHelper.assertNumber(content, matcher);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the {@link Double} value found.
|
||||
*/
|
||||
public ResultMatcher number(Double value) {
|
||||
return number(Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the XPath and assert the {@link Boolean} value found.
|
||||
*/
|
||||
public ResultMatcher booleanValue(final Boolean value) {
|
||||
return new ResultMatcher() {
|
||||
public void match(MvcResult result) throws Exception {
|
||||
String content = result.getResponse().getContentAsString();
|
||||
xpathHelper.assertBoolean(content, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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.setup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.MockMvcBuilder;
|
||||
import org.springframework.test.web.mock.servlet.MockMvcBuilderSupport;
|
||||
import org.springframework.test.web.mock.servlet.RequestBuilder;
|
||||
import org.springframework.test.web.mock.servlet.ResultHandler;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* An concrete implementation of {@link MockMvcBuilder} with methods for
|
||||
* configuring filters, default request properties, and global expectations and
|
||||
* result actions.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public class DefaultMockMvcBuilder<Self extends MockMvcBuilder> extends MockMvcBuilderSupport
|
||||
implements MockMvcBuilder {
|
||||
|
||||
private final WebApplicationContext webAppContext;
|
||||
|
||||
private List<Filter> filters = new ArrayList<Filter>();
|
||||
|
||||
private RequestBuilder defaultRequestBuilder;
|
||||
|
||||
private final List<ResultMatcher> globalResultMatchers = new ArrayList<ResultMatcher>();
|
||||
|
||||
private final List<ResultHandler> globalResultHandlers = new ArrayList<ResultHandler>();
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor. Not intended for direct instantiation.
|
||||
* @see MockMvcBuilders#webAppContextSetup(WebApplicationContext)
|
||||
*/
|
||||
protected DefaultMockMvcBuilder(WebApplicationContext webAppContext) {
|
||||
Assert.notNull(webAppContext, "WebApplicationContext is required");
|
||||
Assert.notNull(webAppContext.getServletContext(), "WebApplicationContext must have a ServletContext");
|
||||
this.webAppContext = webAppContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filters mapped to any request (i.e. "/*"). For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* mockMvcBuilder.addFilters(springSecurityFilterChain);
|
||||
* </pre>
|
||||
*
|
||||
* <p>is the equivalent of the following web.xml configuration:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <filter-mapping>
|
||||
* <filter-name>springSecurityFilterChain</filter-name>
|
||||
* <url-pattern>/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* </pre>
|
||||
*
|
||||
* <p>Filters will be invoked in the order in which they are provided.
|
||||
*
|
||||
* @param filters the filters to add
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Self> T addFilters(Filter... filters) {
|
||||
Assert.notNull(filters, "filters cannot be null");
|
||||
|
||||
for(Filter f : filters) {
|
||||
Assert.notNull(f, "filters cannot contain null values");
|
||||
this.filters.add(f);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter mapped to a specific set of patterns. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* mockMvcBuilder.addFilters(myResourceFilter, "/resources/*");
|
||||
* </pre>
|
||||
*
|
||||
* <p>is the equivalent of:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <filter-mapping>
|
||||
* <filter-name>myResourceFilter</filter-name>
|
||||
* <url-pattern>/resources/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* </pre>
|
||||
*
|
||||
* <p>Filters will be invoked in the order in which they are provided.
|
||||
*
|
||||
* @param filter the filter to add
|
||||
* @param urlPatterns URL patterns to map to; if empty, "/*" is used by default
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Self> T addFilter(Filter filter, String... urlPatterns) {
|
||||
|
||||
Assert.notNull(filter, "filter cannot be null");
|
||||
Assert.notNull(urlPatterns, "urlPatterns cannot be null");
|
||||
|
||||
if(urlPatterns.length > 0) {
|
||||
filter = new PatternMappingFilterProxy(filter, urlPatterns);
|
||||
}
|
||||
|
||||
this.filters.add(filter);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define default request properties that should be merged into all
|
||||
* performed requests. In effect this provides a mechanism for defining
|
||||
* common initialization for all requests such as the content type, request
|
||||
* parameters, session attributes, and any other request property.
|
||||
*
|
||||
* <p>Properties specified at the time of performing a request override the
|
||||
* default properties defined here.
|
||||
*
|
||||
* @param requestBuilder a RequestBuilder; see static factory methods in
|
||||
* {@link org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders}
|
||||
* .
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Self> T defaultRequest(RequestBuilder requestBuilder) {
|
||||
this.defaultRequestBuilder = requestBuilder;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a global expectation that should <em>always</em> be applied to
|
||||
* every response. For example, status code 200 (OK), content type
|
||||
* {@code "application/json"}, etc.
|
||||
*
|
||||
* @param resultMatcher a ResultMatcher; see static factory methods in
|
||||
* {@link org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Self> T alwaysExpect(ResultMatcher resultMatcher) {
|
||||
this.globalResultMatchers.add(resultMatcher);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a global action that should <em>always</em> be applied to every
|
||||
* response. For example, writing detailed information about the performed
|
||||
* request and resulting response to {@code System.out}.
|
||||
*
|
||||
* @param resultHandler a ResultHandler; see static factory methods in
|
||||
* {@link org.springframework.test.web.mock.servlet.result.MockMvcResultHandlers}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends Self> T alwaysDo(ResultHandler resultHandler) {
|
||||
this.globalResultHandlers.add(resultHandler);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link MockMvc} instance.
|
||||
*/
|
||||
public final MockMvc build() {
|
||||
|
||||
initWebAppContext(this.webAppContext);
|
||||
|
||||
ServletContext servletContext = this.webAppContext.getServletContext();
|
||||
MockServletConfig mockServletConfig = new MockServletConfig(servletContext);
|
||||
|
||||
Filter[] filterArray = this.filters.toArray(new Filter[this.filters.size()]);
|
||||
|
||||
return super.createMockMvc(filterArray, mockServletConfig, this.webAppContext,
|
||||
this.defaultRequestBuilder, this.globalResultMatchers, this.globalResultHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked from {@link #build()} before the {@link MockMvc} instance is created.
|
||||
* Allows sub-classes to further initialize the {@code WebApplicationContext}
|
||||
* and the {@code javax.servlet.ServletContext} it contains.
|
||||
*/
|
||||
protected void initWebAppContext(WebApplicationContext webAppContext) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.setup;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.MockMvcBuilder;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
/**
|
||||
* The main class to import to access all available {@link MockMvcBuilder}s.
|
||||
*
|
||||
* <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 class MockMvcBuilders {
|
||||
|
||||
/**
|
||||
* Build a {@link MockMvc} using the given, fully initialized, i.e.
|
||||
* refreshed, {@link WebApplicationContext}. The {@link DispatcherServlet}
|
||||
* will use the context to discover Spring MVC infrastructure and
|
||||
* application controllers in it. The context must have been configured with
|
||||
* a {@link ServletContext}.
|
||||
*/
|
||||
public static DefaultMockMvcBuilder<DefaultMockMvcBuilder<?>> webAppContextSetup(WebApplicationContext context) {
|
||||
return new DefaultMockMvcBuilder<DefaultMockMvcBuilder<?>>(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link MockMvc} by registering one or more {@code @Controller}'s
|
||||
* instances and configuring Spring MVC infrastructure programmatically.
|
||||
* This allows full control over the instantiation and initialization of
|
||||
* controllers, and their dependencies, similar to plain unit tests while
|
||||
* also making it possible to test one controller at a time.
|
||||
*
|
||||
* <p>When this option is used, the minimum infrastructure required by the
|
||||
* {@link DispatcherServlet} to serve requests with annotated controllers is
|
||||
* automatically created, and can be customized, resulting in configuration
|
||||
* that is equivalent to what the MVC Java configuration provides except
|
||||
* using builder style methods.
|
||||
*
|
||||
* <p>If the Spring MVC configuration of an application is relatively
|
||||
* straight-forward, for example when using the MVC namespace or the MVC
|
||||
* Java config, then using this builder might be a good option for testing
|
||||
* a majority of controllers. A much smaller number of tests can be used
|
||||
* to focus on testing and verifying the actual Spring MVC configuration.
|
||||
*
|
||||
* @param controllers one or more {@link Controller @Controller}'s to test
|
||||
*/
|
||||
public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers) {
|
||||
return new StandaloneMockMvcBuilder(controllers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.setup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* A Filter that invokes a delegate {@link Filter} only if the request URL
|
||||
* matches the pattern it is mapped to using pattern matching as defined in the
|
||||
* Servlet spec.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
final class PatternMappingFilterProxy implements Filter {
|
||||
|
||||
private static final String EXTENSION_MAPPING_PATTERN = "*.";
|
||||
|
||||
private static final String PATH_MAPPING_PATTERN = "/*";
|
||||
|
||||
private static final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
private final Filter delegate;
|
||||
|
||||
/** Patterns that require an exact match, e.g. "/test" */
|
||||
private final List<String> exactMatches = new ArrayList<String>();
|
||||
|
||||
/** Patterns that require the URL to have a specific prefix, e.g. "/test/*" */
|
||||
private final List<String> startsWithMatches = new ArrayList<String>();
|
||||
|
||||
/** Patterns that require the request URL to have a specific suffix, e.g. "*.html" */
|
||||
private final List<String> endsWithMatches = new ArrayList<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public PatternMappingFilterProxy(Filter delegate, String... urlPatterns) {
|
||||
Assert.notNull(delegate, "A delegate Filter is required");
|
||||
this.delegate = delegate;
|
||||
for(String urlPattern : urlPatterns) {
|
||||
addUrlPattern(urlPattern);
|
||||
}
|
||||
}
|
||||
|
||||
private void addUrlPattern(String urlPattern) {
|
||||
Assert.notNull(urlPattern, "Found null URL Pattern");
|
||||
if(urlPattern.startsWith(EXTENSION_MAPPING_PATTERN)) {
|
||||
this.endsWithMatches.add(urlPattern.substring(1, urlPattern.length()));
|
||||
} else if(urlPattern.equals(PATH_MAPPING_PATTERN)) {
|
||||
this.startsWithMatches.add("");
|
||||
}
|
||||
else if (urlPattern.endsWith(PATH_MAPPING_PATTERN)) {
|
||||
this.startsWithMatches.add(urlPattern.substring(0, urlPattern.length() - 1));
|
||||
this.exactMatches.add(urlPattern.substring(0, urlPattern.length() - 2));
|
||||
} else {
|
||||
if("".equals(urlPattern)) {
|
||||
urlPattern = "/";
|
||||
}
|
||||
this.exactMatches.add(urlPattern);
|
||||
}
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
String requestPath = urlPathHelper.getPathWithinApplication(httpRequest);
|
||||
|
||||
if(matches(requestPath)) {
|
||||
this.delegate.doFilter(request, response, filterChain);
|
||||
} else {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matches(String requestPath) {
|
||||
for(String pattern : this.exactMatches) {
|
||||
if(pattern.equals(requestPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(!requestPath.startsWith("/")) {
|
||||
return false;
|
||||
}
|
||||
for(String pattern : this.endsWithMatches) {
|
||||
if(requestPath.endsWith(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for(String pattern : this.startsWithMatches) {
|
||||
if(requestPath.startsWith(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.delegate.init(filterConfig);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
this.delegate.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* 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.setup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationObjectSupport;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.FlashMapManager;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
import org.springframework.web.servlet.handler.MappedInterceptor;
|
||||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.support.SessionFlashMapManager;
|
||||
import org.springframework.web.servlet.theme.FixedThemeResolver;
|
||||
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
|
||||
/**
|
||||
* A MockMvcBuilder that accepts {@code @Controller} registrations thus allowing
|
||||
* full control over the instantiation and the initialization of controllers and
|
||||
* their dependencies similar to plain unit tests, and also making it possible
|
||||
* to test one controller at a time.
|
||||
*
|
||||
* <p>This builder creates the minimum infrastructure required by the
|
||||
* {@link DispatcherServlet} to serve requests with annotated controllers and
|
||||
* also provides methods to customize it. The resulting configuration and
|
||||
* customizations possible are equivalent to using the MVC Java config except
|
||||
* using builder style methods.
|
||||
*
|
||||
* <p>To configure view resolution, either select a "fixed" view to use for every
|
||||
* performed request (see {@link #setSingleView(View)}) or provide a list of
|
||||
* {@code ViewResolver}'s, see {@link #setViewResolvers(ViewResolver...)}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMockMvcBuilder> {
|
||||
|
||||
private final Object[] controllers;
|
||||
|
||||
private List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
private List<HandlerMethodArgumentResolver> customArgumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
|
||||
|
||||
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||
|
||||
private final List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();
|
||||
|
||||
private Validator validator = null;
|
||||
|
||||
private FormattingConversionService conversionService = null;
|
||||
|
||||
private List<HandlerExceptionResolver> handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>();
|
||||
|
||||
private List<ViewResolver> viewResolvers;
|
||||
|
||||
private LocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
|
||||
|
||||
private FlashMapManager flashMapManager = null;
|
||||
|
||||
private boolean useSuffixPatternMatch = true;
|
||||
|
||||
private boolean useTrailingSlashPatternMatch = true;
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor. Not intended for direct instantiation.
|
||||
* @see MockMvcBuilders#standaloneSetup(Object...)
|
||||
*/
|
||||
protected StandaloneMockMvcBuilder(Object... controllers) {
|
||||
super(new StubWebApplicationContext(new MockServletContext()));
|
||||
Assert.isTrue(!ObjectUtils.isEmpty(controllers), "At least one controller is required");
|
||||
this.controllers = controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message converters to use in argument resolvers and in return value
|
||||
* handlers, which support reading and/or writing to the body of the request
|
||||
* and response. If no message converters are added to the list, a default
|
||||
* list of converters is added instead.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setMessageConverters(HttpMessageConverter<?>...messageConverters) {
|
||||
this.messageConverters = Arrays.asList(messageConverters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a custom {@link Validator} instead of the one created by default.
|
||||
* The default implementation used, assuming JSR-303 is on the classpath, is
|
||||
* {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setValidator(Validator validator) {
|
||||
this.validator = validator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a conversion service with custom formatters and converters.
|
||||
* If not set, a {@link DefaultFormattingConversionService} is used by default.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setConversionService(FormattingConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add interceptors mapped to all incoming requests.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder addInterceptors(HandlerInterceptor... interceptors) {
|
||||
addMappedInterceptors(null, interceptors);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add interceptors mapped to a set of path patterns.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder addMappedInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) {
|
||||
for (HandlerInterceptor interceptor : interceptors) {
|
||||
this.mappedInterceptors.add(new MappedInterceptor(pathPatterns, interceptor));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide custom resolvers for controller method arguments.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setCustomArgumentResolvers(HandlerMethodArgumentResolver... argumentResolvers) {
|
||||
this.customArgumentResolvers = Arrays.asList(argumentResolvers);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide custom handlers for controller method return values.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setCustomReturnValueHandlers(HandlerMethodReturnValueHandler... handlers) {
|
||||
this.customReturnValueHandlers = Arrays.asList(handlers);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the HandlerExceptionResolver types to use.
|
||||
*/
|
||||
public void setHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
|
||||
this.handlerExceptionResolvers = exceptionResolvers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up view resolution with the given {@link ViewResolver}s.
|
||||
* If not set, an {@link InternalResourceViewResolver} is used by default.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setViewResolvers(ViewResolver...resolvers) {
|
||||
this.viewResolvers = Arrays.asList(resolvers);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a single {@link ViewResolver} that always returns the provided
|
||||
* view instance. This is a convenient shortcut if you need to use one
|
||||
* View instance only -- e.g. rendering generated content (JSON, XML, Atom).
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setSingleView(View view) {
|
||||
this.viewResolvers = Collections.<ViewResolver>singletonList(new StaticViewResolver(view));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a LocaleResolver instance.
|
||||
* If not provided, the default one used is {@link AcceptHeaderLocaleResolver}.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setLocaleResolver(LocaleResolver localeResolver) {
|
||||
this.localeResolver = localeResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a custom FlashMapManager instance.
|
||||
* If not provided, {@code SessionFlashMapManager} is used by default.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setFlashMapManager(FlashMapManager flashMapManager) {
|
||||
this.flashMapManager = flashMapManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to use suffix pattern match (".*") when matching patterns to
|
||||
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
||||
* <p>The default value is {@code true}.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
* If enabled a method mapped to "/users" also matches to "/users/".
|
||||
* <p>The default value is {@code true}.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder setUseTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch) {
|
||||
this.useTrailingSlashPatternMatch = useTrailingSlashPatternMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void initWebAppContext(WebApplicationContext cxt) {
|
||||
StubWebApplicationContext mockCxt = (StubWebApplicationContext) cxt;
|
||||
registerMvcSingletons(mockCxt);
|
||||
cxt.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, mockCxt);
|
||||
}
|
||||
|
||||
private void registerMvcSingletons(StubWebApplicationContext cxt) {
|
||||
|
||||
StandaloneConfiguration configuration = new StandaloneConfiguration();
|
||||
|
||||
RequestMappingHandlerMapping handlerMapping = configuration.requestMappingHandlerMapping();
|
||||
handlerMapping.setServletContext(cxt.getServletContext());
|
||||
handlerMapping.setApplicationContext(cxt);
|
||||
cxt.addBean("requestMappingHandlerMapping", handlerMapping);
|
||||
|
||||
RequestMappingHandlerAdapter handlerAdapter = configuration.requestMappingHandlerAdapter();
|
||||
handlerAdapter.setServletContext(cxt.getServletContext());
|
||||
handlerAdapter.setApplicationContext(cxt);
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
cxt.addBean("requestMappingHandlerAdapter", handlerAdapter);
|
||||
|
||||
cxt.addBean("handlerExceptionResolver", configuration.handlerExceptionResolver());
|
||||
|
||||
cxt.addBeans(initViewResolvers(cxt));
|
||||
cxt.addBean(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME, this.localeResolver);
|
||||
cxt.addBean(DispatcherServlet.THEME_RESOLVER_BEAN_NAME, new FixedThemeResolver());
|
||||
cxt.addBean(DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, new DefaultRequestToViewNameTranslator());
|
||||
|
||||
this.flashMapManager = new SessionFlashMapManager();
|
||||
cxt.addBean(DispatcherServlet.FLASH_MAP_MANAGER_BEAN_NAME, this.flashMapManager);
|
||||
}
|
||||
|
||||
private List<ViewResolver> initViewResolvers(WebApplicationContext wac) {
|
||||
|
||||
this.viewResolvers = (this.viewResolvers == null) ?
|
||||
Arrays.<ViewResolver>asList(new InternalResourceViewResolver()) : this.viewResolvers;
|
||||
|
||||
for (Object viewResolver : this.viewResolvers) {
|
||||
if (viewResolver instanceof WebApplicationObjectSupport) {
|
||||
((WebApplicationObjectSupport) viewResolver).setApplicationContext(wac);
|
||||
}
|
||||
}
|
||||
|
||||
return this.viewResolvers;
|
||||
}
|
||||
|
||||
|
||||
/** Using the MVC Java configuration as the starting point for the "standalone" setup */
|
||||
private class StandaloneConfiguration extends WebMvcConfigurationSupport {
|
||||
|
||||
@Override
|
||||
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
|
||||
|
||||
StaticRequestMappingHandlerMapping handlerMapping = new StaticRequestMappingHandlerMapping();
|
||||
handlerMapping.registerHandlers(controllers);
|
||||
|
||||
handlerMapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
|
||||
handlerMapping.setUseTrailingSlashMatch(useTrailingSlashPatternMatch);
|
||||
handlerMapping.setOrder(0);
|
||||
handlerMapping.setInterceptors(getInterceptors());
|
||||
|
||||
return handlerMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.addAll(messageConverters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.addAll(customArgumentResolvers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
|
||||
returnValueHandlers.addAll(customReturnValueHandlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInterceptors(InterceptorRegistry registry) {
|
||||
for (MappedInterceptor interceptor : mappedInterceptors) {
|
||||
InterceptorRegistration registration = registry.addInterceptor(interceptor.getInterceptor());
|
||||
if (interceptor.getPathPatterns() != null) {
|
||||
registration.addPathPatterns(interceptor.getPathPatterns());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormattingConversionService mvcConversionService() {
|
||||
return (conversionService != null) ? conversionService : super.mvcConversionService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Validator mvcValidator() {
|
||||
Validator mvcValidator = (validator != null) ? validator : super.mvcValidator();
|
||||
if (mvcValidator instanceof InitializingBean) {
|
||||
try {
|
||||
((InitializingBean) mvcValidator).afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new BeanInitializationException("Failed to initialize Validator", e);
|
||||
}
|
||||
}
|
||||
return mvcValidator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
|
||||
exceptionResolvers.addAll(StandaloneMockMvcBuilder.this.handlerExceptionResolvers);
|
||||
}
|
||||
}
|
||||
|
||||
/** A {@code RequestMappingHandlerMapping} that allows registration of controllers */
|
||||
private static class StaticRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
||||
|
||||
public void registerHandlers(Object...handlers) {
|
||||
for (Object handler : handlers) {
|
||||
super.detectHandlerMethods(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A {@link ViewResolver} that always returns same View */
|
||||
private static class StaticViewResolver implements ViewResolver {
|
||||
|
||||
private final View view;
|
||||
|
||||
public StaticViewResolver(View view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public View resolveViewName(String viewName, Locale locale) throws Exception {
|
||||
return this.view;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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.setup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceResolvable;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.context.support.DelegatingMessageSource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
|
||||
|
||||
/**
|
||||
* A mock WebApplicationContext that accepts registrations of object instances.
|
||||
*
|
||||
* <p>As registered object instances are instantiated and initialized
|
||||
* externally, there is no wiring, bean initialization, lifecycle events, as
|
||||
* well as no pre-processing and post-processing hooks typically associated with
|
||||
* beans managed by an {@link ApplicationContext}. Just a simple lookup into a
|
||||
* {@link StaticListableBeanFactory}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
class StubWebApplicationContext implements WebApplicationContext {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
private final StubBeanFactory beanFactory = new StubBeanFactory();
|
||||
|
||||
private final String id = ObjectUtils.identityToString(this);
|
||||
|
||||
private final String displayName = ObjectUtils.identityToString(this);
|
||||
|
||||
private final long startupDate = System.currentTimeMillis();
|
||||
|
||||
private final Environment environment = new StandardEnvironment();
|
||||
|
||||
private final MessageSource messageSource = new DelegatingMessageSource();
|
||||
|
||||
private final ResourcePatternResolver resourcePatternResolver;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public StubWebApplicationContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
this.resourcePatternResolver = new ServletContextResourcePatternResolver(servletContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance that can initialize {@link ApplicationContextAware} beans.
|
||||
*/
|
||||
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ApplicationContext interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getApplicationName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public long getStartupDate() {
|
||||
return this.startupDate;
|
||||
}
|
||||
|
||||
public ApplicationContext getParent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Environment getEnvironment() {
|
||||
return this.environment ;
|
||||
}
|
||||
|
||||
public void addBean(String name, Object bean) {
|
||||
this.beanFactory.addBean(name, bean);
|
||||
}
|
||||
|
||||
public void addBeans(List<?> beans) {
|
||||
for (Object bean : beans) {
|
||||
String name = bean.getClass().getName() + "#" + ObjectUtils.getIdentityHexString(bean);
|
||||
this.beanFactory.addBean(name, bean);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of BeanFactory interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public Object getBean(String name) throws BeansException {
|
||||
return this.beanFactory.getBean(name);
|
||||
}
|
||||
|
||||
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
|
||||
return this.beanFactory.getBean(name, requiredType);
|
||||
}
|
||||
|
||||
public <T> T getBean(Class<T> requiredType) throws BeansException {
|
||||
return this.beanFactory.getBean(requiredType);
|
||||
}
|
||||
|
||||
public Object getBean(String name, Object... args) throws BeansException {
|
||||
return this.beanFactory.getBean(name, args);
|
||||
}
|
||||
|
||||
public boolean containsBean(String name) {
|
||||
return this.beanFactory.containsBean(name);
|
||||
}
|
||||
|
||||
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
|
||||
return this.beanFactory.isSingleton(name);
|
||||
}
|
||||
|
||||
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
|
||||
return this.beanFactory.isPrototype(name);
|
||||
}
|
||||
|
||||
public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException {
|
||||
return this.beanFactory.isTypeMatch(name, targetType);
|
||||
}
|
||||
|
||||
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
|
||||
return this.beanFactory.getType(name);
|
||||
}
|
||||
|
||||
public String[] getAliases(String name) {
|
||||
return this.beanFactory.getAliases(name);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ListableBeanFactory interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public boolean containsBeanDefinition(String beanName) {
|
||||
return this.beanFactory.containsBeanDefinition(beanName);
|
||||
}
|
||||
|
||||
public int getBeanDefinitionCount() {
|
||||
return this.beanFactory.getBeanDefinitionCount();
|
||||
}
|
||||
|
||||
public String[] getBeanDefinitionNames() {
|
||||
return this.beanFactory.getBeanDefinitionNames();
|
||||
}
|
||||
|
||||
public String[] getBeanNamesForType(Class<?> type) {
|
||||
return this.beanFactory.getBeanNamesForType(type);
|
||||
}
|
||||
|
||||
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||
return this.beanFactory.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
|
||||
}
|
||||
|
||||
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
|
||||
return this.beanFactory.getBeansOfType(type);
|
||||
}
|
||||
|
||||
public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
|
||||
throws BeansException {
|
||||
|
||||
return this.beanFactory.getBeansOfType(type, includeNonSingletons, allowEagerInit);
|
||||
}
|
||||
|
||||
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
|
||||
throws BeansException {
|
||||
|
||||
return this.beanFactory.getBeansWithAnnotation(annotationType);
|
||||
}
|
||||
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) {
|
||||
return this.beanFactory.findAnnotationOnBean(beanName, annotationType);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of HierarchicalBeanFactory interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public BeanFactory getParentBeanFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean containsLocalBean(String name) {
|
||||
return this.beanFactory.containsBean(name);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of MessageSource interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public String getMessage(String code, Object args[], String defaultMessage, Locale locale) {
|
||||
return this.messageSource.getMessage(code, args, defaultMessage, locale);
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object args[], Locale locale) throws NoSuchMessageException {
|
||||
return this.messageSource.getMessage(code, args, locale);
|
||||
}
|
||||
|
||||
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
|
||||
return this.messageSource.getMessage(resolvable, locale);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ResourceLoader interface
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Resource getResource(String location) {
|
||||
return this.resourcePatternResolver.getResource(location);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Other
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
}
|
||||
|
||||
public Resource[] getResources(String locationPattern) throws IOException {
|
||||
return this.resourcePatternResolver.getResources(locationPattern);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An extension of StaticListableBeanFactory that implements
|
||||
* AutowireCapableBeanFactory in order to allow bean initialization of
|
||||
* {@link ApplicationContextAware} singletons.
|
||||
*/
|
||||
private class StubBeanFactory extends StaticListableBeanFactory implements AutowireCapableBeanFactory {
|
||||
|
||||
public Object initializeBean(Object existingBean, String beanName) throws BeansException {
|
||||
if (existingBean instanceof ApplicationContextAware) {
|
||||
((ApplicationContextAware) existingBean).setApplicationContext(StubWebApplicationContext.this);
|
||||
}
|
||||
return existingBean;
|
||||
}
|
||||
|
||||
public <T> T createBean(Class<T> beanClass) throws BeansException {
|
||||
throw new UnsupportedOperationException("Bean creation is not supported");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
throw new UnsupportedOperationException("Bean creation is not supported");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void autowireBean(Object existingBean) throws BeansException {
|
||||
throw new UnsupportedOperationException("Autowiring is not supported");
|
||||
}
|
||||
|
||||
public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException {
|
||||
throw new UnsupportedOperationException("Autowiring is not supported");
|
||||
}
|
||||
|
||||
public Object configureBean(Object existingBean, String beanName) throws BeansException {
|
||||
throw new UnsupportedOperationException("Configuring a bean is not supported");
|
||||
}
|
||||
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
|
||||
throw new UnsupportedOperationException("Dependency resolution is not supported");
|
||||
}
|
||||
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames,
|
||||
TypeConverter typeConverter) throws BeansException {
|
||||
throw new UnsupportedOperationException("Dependency resolution is not supported");
|
||||
}
|
||||
|
||||
public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
|
||||
throw new UnsupportedOperationException("Bean property initialization is not supported");
|
||||
}
|
||||
|
||||
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
|
||||
throws BeansException {
|
||||
throw new UnsupportedOperationException("Post processing is not supported");
|
||||
}
|
||||
|
||||
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
|
||||
throws BeansException {
|
||||
throw new UnsupportedOperationException("Post processing is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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;
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import static org.springframework.test.web.mock.AssertionErrors.assertTrue;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import com.jayway.jsonpath.InvalidPathException;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* A helper class for applying assertions via JSONPath expressions.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class JsonPathExpectationsHelper {
|
||||
|
||||
private final String expression;
|
||||
|
||||
private final JsonPath jsonPath;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @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...)}
|
||||
*/
|
||||
public JsonPathExpectationsHelper(String expression, Object ... args) {
|
||||
this.expression = String.format(expression, args);
|
||||
this.jsonPath = JsonPath.compile(this.expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the JSONPath and assert the resulting value with the given {@code Matcher}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void assertValue(String content, Matcher<T> matcher) throws ParseException {
|
||||
T value = (T) evaluateJsonPath(content);
|
||||
MatcherAssert.assertThat("JSON path: " + this.expression, value, matcher);
|
||||
}
|
||||
|
||||
private Object evaluateJsonPath(String content) throws ParseException {
|
||||
String message = "No value for JSON path: " + this.expression + ", exception: ";
|
||||
try {
|
||||
return this.jsonPath.read(content);
|
||||
}
|
||||
catch (InvalidPathException ex) {
|
||||
throw new AssertionError(message + ex.getMessage());
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException ex) {
|
||||
throw new AssertionError(message + ex.getMessage());
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new AssertionError(message + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the JSONPath and assert the resulting value.
|
||||
*/
|
||||
public void assertValue(Object value) throws ParseException {
|
||||
assertValue(Matchers.equalTo(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the JSON path and assert the resulting content exists.
|
||||
*/
|
||||
public void exists(String content) throws ParseException {
|
||||
Object value = evaluateJsonPath(content);
|
||||
String reason = "No value for JSON path: " + this.expression;
|
||||
assertTrue(reason, value != null);
|
||||
if (List.class.isInstance(value)) {
|
||||
assertTrue(reason, !((List<?>) value).isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the JSON path and assert it doesn't point to any content.
|
||||
*/
|
||||
public void doesNotExist(String content) throws ParseException {
|
||||
|
||||
Object value;
|
||||
try {
|
||||
value = evaluateJsonPath(content);
|
||||
}
|
||||
catch (AssertionError ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
String reason = String.format("Expected no value for JSON path: %s but found: %s", this.expression, value);
|
||||
if (List.class.isInstance(value)) {
|
||||
assertTrue(reason, ((List<?>) value).isEmpty());
|
||||
}
|
||||
else {
|
||||
assertTrue(reason, value == null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import org.custommonkey.xmlunit.Diff;
|
||||
import org.custommonkey.xmlunit.XMLUnit;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.springframework.test.web.mock.AssertionErrors;
|
||||
import org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* A helper class for assertions on XML content.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class XmlExpectationsHelper {
|
||||
|
||||
|
||||
/**
|
||||
* Parse the content as {@link Node} and apply a {@link Matcher}.
|
||||
* @see org.hamcrest.Matchers#hasXPath
|
||||
*/
|
||||
public void assertNode(String content, Matcher<? super Node> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
MatcherAssert.assertThat("Body content", document, matcher);
|
||||
}
|
||||
|
||||
private Document parseXmlString(String xml) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
|
||||
InputSource inputSource = new InputSource(new StringReader(xml));
|
||||
Document document = documentBuilder.parse(inputSource);
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the content as {@link DOMSource} and apply a {@link Matcher}.
|
||||
* @see <a href="http://code.google.com/p/xml-matchers/">xml-matchers</a>
|
||||
*/
|
||||
public void assertSource(String content, Matcher<? super Source> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
MatcherAssert.assertThat("Body content", new DOMSource(document), matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the expected and actual content strings 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 method assumes the
|
||||
* <a href="http://xmlunit.sourceforge.net/">XMLUnit<a/> library is available.
|
||||
*
|
||||
* @param expected the expected XML content
|
||||
* @param actual the actual XML content
|
||||
*
|
||||
* @see MockMvcResultMatchers#xpath(String, Object...)
|
||||
* @see MockMvcResultMatchers#xpath(String, Map, Object...)
|
||||
*/
|
||||
public void assertXmlEqual(String expected, String actual) throws Exception {
|
||||
Document control = XMLUnit.buildControlDocument(expected);
|
||||
Document test = XMLUnit.buildTestDocument(actual);
|
||||
Diff diff = new Diff(control, test);
|
||||
if (!diff.similar()) {
|
||||
AssertionErrors.fail("Body content " + diff.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import static org.springframework.test.web.mock.AssertionErrors.assertEquals;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.springframework.util.xml.SimpleNamespaceContext;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
/**
|
||||
* A helper class for applying assertions via XPath expressions.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
*/
|
||||
public class XpathExpectationsHelper {
|
||||
|
||||
private final String expression;
|
||||
|
||||
private final XPathExpression xpathExpression;
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public XpathExpectationsHelper(String expression, Map<String, String> namespaces, Object... args)
|
||||
throws XPathExpressionException {
|
||||
|
||||
this.expression = String.format(expression, args);
|
||||
this.xpathExpression = compileXpathExpression(this.expression, namespaces);
|
||||
}
|
||||
|
||||
private XPathExpression compileXpathExpression(String expression, Map<String, String> namespaces)
|
||||
throws XPathExpressionException {
|
||||
|
||||
SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
|
||||
namespaceContext.setBindings((namespaces != null) ? namespaces : Collections.<String, String> emptyMap());
|
||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
xpath.setNamespaceContext(namespaceContext);
|
||||
return xpath.compile(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the compiled XPath expression.
|
||||
*/
|
||||
protected XPathExpression getXpathExpression() {
|
||||
return this.xpathExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the content, evaluate the XPath expression as a {@link Node}, and
|
||||
* assert it with the given {@code Matcher<Node>}.
|
||||
*/
|
||||
public void assertNode(String content, final Matcher<? super Node> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
Node node = evaluateXpath(document, XPathConstants.NODE, Node.class);
|
||||
MatcherAssert.assertThat("Xpath: " + XpathExpectationsHelper.this.expression, node, matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given XML content to a {@link Document}.
|
||||
*
|
||||
* @param xml the content to parse
|
||||
* @return the parsed document
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected Document parseXmlString(String xml) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
|
||||
InputSource inputSource = new InputSource(new StringReader(xml));
|
||||
Document document = documentBuilder.parse(inputSource);
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression to given document.
|
||||
* @throws XPathExpressionException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T evaluateXpath(Document document, QName evaluationType, Class<T> expectedClass)
|
||||
throws XPathExpressionException {
|
||||
|
||||
return (T) getXpathExpression().evaluate(document, evaluationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content exists.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void exists(String content) throws Exception {
|
||||
assertNode(content, Matchers.notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content does not exist.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void doesNotExist(String content) throws Exception {
|
||||
assertNode(content, Matchers.nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content with the
|
||||
* given Hamcrest matcher.
|
||||
*
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertNodeCount(String content, Matcher<Integer> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
NodeList nodeList = evaluateXpath(document, XPathConstants.NODESET, NodeList.class);
|
||||
String reason = "nodeCount Xpath: " + XpathExpectationsHelper.this.expression;
|
||||
MatcherAssert.assertThat(reason, nodeList.getLength(), matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content as an integer.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertNodeCount(String content, int expectedCount) throws Exception {
|
||||
assertNodeCount(content, Matchers.equalTo(expectedCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content with the
|
||||
* given Hamcrest matcher.
|
||||
*
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertString(String content, Matcher<? super String> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
String result = evaluateXpath(document, XPathConstants.STRING, String.class);
|
||||
MatcherAssert.assertThat("Xpath: " + XpathExpectationsHelper.this.expression, result, matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content as a String.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertString(String content, String expectedValue) throws Exception {
|
||||
assertString(content, Matchers.equalTo(expectedValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content with the
|
||||
* given Hamcrest matcher.
|
||||
*
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertNumber(String content, Matcher<? super Double> matcher) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
Double result = evaluateXpath(document, XPathConstants.NUMBER, Double.class);
|
||||
MatcherAssert.assertThat("Xpath: " + XpathExpectationsHelper.this.expression, result, matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content as a Double.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertNumber(String content, Double expectedValue) throws Exception {
|
||||
assertNumber(content, Matchers.equalTo(expectedValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the XPath expression and assert the resulting content as a Boolean.
|
||||
* @throws Exception if content parsing or expression evaluation fails
|
||||
*/
|
||||
public void assertBoolean(String content, boolean expectedValue) throws Exception {
|
||||
Document document = parseXmlString(content);
|
||||
String result = evaluateXpath(document, XPathConstants.STRING, String.class);
|
||||
assertEquals("Xpath:", expectedValue, Boolean.parseBoolean(result));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support classes shared among client and server-side Spring MVC Test classes.
|
||||
*/
|
||||
package org.springframework.test.web.mock.support;
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@XmlRootElement
|
||||
public class Person {
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
private double someDouble;
|
||||
|
||||
private boolean someBoolean;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Person setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getSomeDouble() {
|
||||
return someDouble;
|
||||
}
|
||||
|
||||
public Person setSomeDouble(double someDouble) {
|
||||
this.someDouble = someDouble;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSomeBoolean() {
|
||||
return someBoolean;
|
||||
}
|
||||
|
||||
public Person setSomeBoolean(boolean someBoolean) {
|
||||
this.someBoolean = someBoolean;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Person)) {
|
||||
return false;
|
||||
}
|
||||
Person otherPerson = (Person) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.name, otherPerson.name) &&
|
||||
ObjectUtils.nullSafeEquals(this.someDouble, otherPerson.someDouble) &&
|
||||
ObjectUtils.nullSafeEquals(this.someBoolean, otherPerson.someBoolean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person [name=" + this.name + ", someDouble=" + this.someDouble
|
||||
+ ", someBoolean=" + this.someBoolean + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.anything;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Tests for {@link MockClientHttpRequestFactory}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MockClientHttpRequestFactoryTests {
|
||||
|
||||
private MockRestServiceServer server;
|
||||
|
||||
private ClientHttpRequestFactory factory;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
this.server = MockRestServiceServer.createServer(restTemplate);
|
||||
this.factory = restTemplate.getRequestFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createRequest() throws Exception {
|
||||
URI uri = new URI("/foo");
|
||||
ClientHttpRequest expected = (ClientHttpRequest) this.server.expect(anything());
|
||||
ClientHttpRequest actual = this.factory.createRequest(uri, HttpMethod.GET);
|
||||
|
||||
assertSame(expected, actual);
|
||||
assertEquals(uri, actual.getURI());
|
||||
assertEquals(HttpMethod.GET, actual.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFurtherRequestsExpected() throws Exception {
|
||||
try {
|
||||
this.factory.createRequest(new URI("/foo"), HttpMethod.GET);
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
assertEquals("No further requests expected", error.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyZeroExpected() throws Exception {
|
||||
this.server.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyExpectedEqualExecuted() throws Exception {
|
||||
this.server.expect(anything());
|
||||
this.server.expect(anything());
|
||||
|
||||
this.factory.createRequest(new URI("/foo"), HttpMethod.GET);
|
||||
this.factory.createRequest(new URI("/bar"), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyMoreExpected() throws Exception {
|
||||
this.server.expect(anything());
|
||||
this.server.expect(anything());
|
||||
|
||||
this.factory.createRequest(new URI("/foo"), HttpMethod.GET);
|
||||
|
||||
try {
|
||||
this.server.verify();
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
assertTrue(error.getMessage(), error.getMessage().contains("1 out of 2 were executed"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.hasXPath;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
import org.springframework.test.web.mock.client.match.ContentRequestMatchers;
|
||||
import org.springframework.test.web.mock.client.match.RequestMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContentRequestMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ContentRequestMatchersTests {
|
||||
|
||||
private MockClientHttpRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.request = new MockClientHttpRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContentType() throws Exception {
|
||||
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
RequestMatchers.content().mimeType("application/json").match(this.request);
|
||||
RequestMatchers.content().mimeType(MediaType.APPLICATION_JSON).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testContentTypeNoMatch1() throws Exception {
|
||||
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
RequestMatchers.content().mimeType("application/xml").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testContentTypeNoMatch2() throws Exception {
|
||||
this.request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
RequestMatchers.content().mimeType(MediaType.APPLICATION_ATOM_XML).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
this.request.getBody().write("test".getBytes());
|
||||
|
||||
RequestMatchers.content().string("test").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testStringNoMatch() throws Exception {
|
||||
this.request.getBody().write("test".getBytes());
|
||||
|
||||
RequestMatchers.content().string("Test").match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytes() throws Exception {
|
||||
byte[] content = "test".getBytes();
|
||||
this.request.getBody().write(content);
|
||||
|
||||
RequestMatchers.content().bytes(content).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testBytesNoMatch() throws Exception {
|
||||
this.request.getBody().write("test".getBytes());
|
||||
|
||||
RequestMatchers.content().bytes("Test".getBytes()).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXml() throws Exception {
|
||||
String content = "<foo><bar>baz</bar><bar>bazz</bar></foo>";
|
||||
this.request.getBody().write(content.getBytes());
|
||||
|
||||
RequestMatchers.content().xml(content).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testXmlNoMatch() throws Exception {
|
||||
this.request.getBody().write("<foo>11</foo>".getBytes());
|
||||
|
||||
RequestMatchers.content().xml("<foo>22</foo>").match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeMatcher() throws Exception {
|
||||
String content = "<foo><bar>baz</bar></foo>";
|
||||
this.request.getBody().write(content.getBytes());
|
||||
|
||||
RequestMatchers.content().node(hasXPath("/foo/bar")).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNodeMatcherNoMatch() throws Exception {
|
||||
String content = "<foo><bar>baz</bar></foo>";
|
||||
this.request.getBody().write(content.getBytes());
|
||||
|
||||
RequestMatchers.content().node(hasXPath("/foo/bar/bar")).match(this.request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
import org.springframework.test.web.mock.client.match.JsonPathRequestMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonPathRequestMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class JsonPathRequestMatchersTests {
|
||||
|
||||
private static final String RESPONSE_CONTENT = "{\"foo\":\"bar\", \"qux\":[\"baz1\",\"baz2\"]}";
|
||||
|
||||
private MockClientHttpRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
this.request = new MockClientHttpRequest();
|
||||
this.request.getBody().write(RESPONSE_CONTENT.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void value() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").value("bar").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void valueNoMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").value("bogus").match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueMatcher() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").value(Matchers.equalTo("bar")).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void valueMatcherNoMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").value(Matchers.equalTo("bogus")).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exists() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").exists().match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void existsNoMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.bogus").exists().match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotExist() throws Exception {
|
||||
new JsonPathRequestMatchers("$.bogus").doesNotExist().match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void doesNotExistNoMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.foo").doesNotExist().match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isArrayMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.qux").isArray().match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void isArrayNoMatch() throws Exception {
|
||||
new JsonPathRequestMatchers("$.bar").isArray().match(this.request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.containsString;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
import org.springframework.test.web.mock.client.match.RequestMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link RequestMatchers}.
|
||||
*
|
||||
* @author Craig Walls
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestMatchersTests {
|
||||
|
||||
private MockClientHttpRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.request = new MockClientHttpRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestTo() throws Exception {
|
||||
this.request.setURI(new URI("http://foo.com/bar"));
|
||||
|
||||
RequestMatchers.requestTo("http://foo.com/bar").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void requestToNoMatch() throws Exception {
|
||||
this.request.setURI(new URI("http://foo.com/bar"));
|
||||
|
||||
RequestMatchers.requestTo("http://foo.com/wrong").match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestToContains() throws Exception {
|
||||
this.request.setURI(new URI("http://foo.com/bar"));
|
||||
|
||||
RequestMatchers.requestTo(containsString("bar")).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void method() throws Exception {
|
||||
this.request.setMethod(HttpMethod.GET);
|
||||
|
||||
RequestMatchers.method(HttpMethod.GET).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void methodNoMatch() throws Exception {
|
||||
this.request.setMethod(HttpMethod.POST);
|
||||
|
||||
RequestMatchers.method(HttpMethod.GET).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void header() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
|
||||
|
||||
RequestMatchers.header("foo", "bar", "baz").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headerMissing() throws Exception {
|
||||
RequestMatchers.header("foo", "bar").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headerMissingValue() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
|
||||
|
||||
RequestMatchers.header("foo", "bad").match(this.request);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void headerContains() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
|
||||
|
||||
RequestMatchers.header("foo", containsString("ba")).match(this.request);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headerContainsWithMissingHeader() throws Exception {
|
||||
RequestMatchers.header("foo", containsString("baz")).match(this.request);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headerContainsWithMissingValue() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
|
||||
|
||||
RequestMatchers.header("foo", containsString("bx")).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headers() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar", "baz"));
|
||||
|
||||
RequestMatchers.header("foo", "bar", "baz").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headersWithMissingHeader() throws Exception {
|
||||
RequestMatchers.header("foo", "bar").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void headersWithMissingValue() throws Exception {
|
||||
this.request.getHeaders().put("foo", Arrays.asList("bar"));
|
||||
|
||||
RequestMatchers.header("foo", "bar", "baz").match(this.request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||
import org.springframework.test.web.mock.client.match.XpathRequestMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link XpathRequestMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class XpathRequestMatchersTests {
|
||||
|
||||
private static final String RESPONSE_CONTENT = "<foo><bar>111</bar><bar>true</bar></foo>";
|
||||
|
||||
private MockClientHttpRequest request;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
this.request = new MockClientHttpRequest();
|
||||
this.request.getBody().write(RESPONSE_CONTENT.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeMatcher() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).node(Matchers.notNullValue()).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNodeMatcherNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).node(Matchers.nullValue()).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExists() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).exists().match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testExistsNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/Bar", null).exists().match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotExist() throws Exception {
|
||||
new XpathRequestMatchers("/foo/Bar", null).doesNotExist().match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testDoesNotExistNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).doesNotExist().match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeCount() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).nodeCount(2).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNodeCountNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar", null).nodeCount(1).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[1]", null).string("111").match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testStringNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[1]", null).string("112").match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumber() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[1]", null).number(111.0).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNumberNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[1]", null).number(111.1).match(this.request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoolean() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[2]", null).booleanValue(true).match(this.request);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testBooleanNoMatch() throws Exception {
|
||||
new XpathRequestMatchers("/foo/bar[2]", null).booleanValue(false).match(this.request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||
import org.springframework.test.web.mock.client.response.DefaultResponseCreator;
|
||||
import org.springframework.test.web.mock.client.response.ResponseCreators;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ResponseCreators} static factory methods.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ResponseCreatorsTests {
|
||||
|
||||
@Test
|
||||
public void success() throws Exception {
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) ResponseCreators.withSuccess().createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successWithContent() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withSuccess("foo", MediaType.TEXT_PLAIN);
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||
assertEquals(MediaType.TEXT_PLAIN, response.getHeaders().getContentType());
|
||||
assertArrayEquals("foo".getBytes(), FileCopyUtils.copyToByteArray(response.getBody()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successWithContentWithoutContentType() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withSuccess("foo", null);
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||
assertNull(response.getHeaders().getContentType());
|
||||
assertArrayEquals("foo".getBytes(), FileCopyUtils.copyToByteArray(response.getBody()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void created() throws Exception {
|
||||
URI location = new URI("/foo");
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withCreatedEntity(location);
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.CREATED, response.getStatusCode());
|
||||
assertEquals(location, response.getHeaders().getLocation());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noContent() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withNoContent();
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void badRequest() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withBadRequest();
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unauthorized() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withUnauthorizedRequest();
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serverError() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withServerError();
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withStatus() throws Exception {
|
||||
DefaultResponseCreator responseCreator = ResponseCreators.withStatus(HttpStatus.FORBIDDEN);
|
||||
MockClientHttpResponse response = (MockClientHttpResponse) responseCreator.createResponse(null);
|
||||
|
||||
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
|
||||
assertTrue(response.getHeaders().isEmpty());
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.method;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Examples to demonstrate writing client-side REST tests with Spring MVC Test.
|
||||
* While the tests in this class invoke the RestTemplate directly, in actual
|
||||
* tests the RestTemplate may likely be invoked indirectly, i.e. through client
|
||||
* code.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class SampleTests {
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performGet() throws Exception {
|
||||
|
||||
String responseBody = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers/42")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Person ludwig = restTemplate.getForObject("/composers/{id}", Person.class, 42);
|
||||
|
||||
// person.getName().equals("Ludwig van Beethoven")
|
||||
// person.getDouble().equals(1.6035)
|
||||
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performGetWithResponseBodyFromFile() throws Exception {
|
||||
|
||||
Resource responseBody = new ClassPathResource("ludwig.json", this.getClass());
|
||||
|
||||
this.mockServer.expect(requestTo("/composers/42")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Person ludwig = restTemplate.getForObject("/composers/{id}", Person.class, 42);
|
||||
|
||||
// hotel.getId() == 42
|
||||
// hotel.getName().equals("Holiday Inn")
|
||||
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verify() {
|
||||
|
||||
this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess("1", MediaType.TEXT_PLAIN));
|
||||
|
||||
this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess("2", MediaType.TEXT_PLAIN));
|
||||
|
||||
this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess("4", MediaType.TEXT_PLAIN));
|
||||
|
||||
this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET))
|
||||
.andRespond(withSuccess("8", MediaType.TEXT_PLAIN));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
String result = this.restTemplate.getForObject("/number", String.class);
|
||||
// result == "1"
|
||||
|
||||
result = this.restTemplate.getForObject("/number", String.class);
|
||||
// result == "2"
|
||||
|
||||
try {
|
||||
this.mockServer.verify();
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
assertTrue(error.getMessage(), error.getMessage().contains("2 out of 4 were executed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.samples.matchers;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Examples of defining expectations on request content and content type.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*
|
||||
* @see JsonPathRequestMatcherTests
|
||||
* @see XmlContentRequestMatcherTests
|
||||
* @see XpathRequestMatcherTests
|
||||
*/
|
||||
public class ContentRequestMatcherTests {
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new StringHttpMessageConverter());
|
||||
converters.add(new MappingJacksonHttpMessageConverter());
|
||||
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.restTemplate.setMessageConverters(converters);
|
||||
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentType() throws Exception {
|
||||
this.mockServer.expect(content().mimeType("application/json;charset=UTF-8")).andRespond(withSuccess());
|
||||
this.restTemplate.put(new URI("/foo"), new Person());
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentTypeNoMatch() throws Exception {
|
||||
this.mockServer.expect(content().mimeType("application/json;charset=UTF-8")).andRespond(withSuccess());
|
||||
try {
|
||||
this.restTemplate.put(new URI("/foo"), "foo");
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
String message = error.getMessage();
|
||||
assertTrue(message, message.startsWith("Content type expected:<application/json;charset=UTF-8>"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentAsString() throws Exception {
|
||||
this.mockServer.expect(content().string("foo")).andRespond(withSuccess());
|
||||
this.restTemplate.put(new URI("/foo"), "foo");
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentStringStartsWith() throws Exception {
|
||||
this.mockServer.expect(content().string(startsWith("foo"))).andRespond(withSuccess());
|
||||
this.restTemplate.put(new URI("/foo"), "foo123");
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentAsBytes() throws Exception {
|
||||
this.mockServer.expect(content().bytes("foo".getBytes())).andRespond(withSuccess());
|
||||
this.restTemplate.put(new URI("/foo"), "foo");
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.samples.matchers;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.header;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Examples of defining expectations on request headers.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class HeaderRequestMatcherTests {
|
||||
|
||||
private static final String RESPONSE_BODY = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}";
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new StringHttpMessageConverter());
|
||||
converters.add(new MappingJacksonHttpMessageConverter());
|
||||
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.restTemplate.setMessageConverters(converters);
|
||||
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
|
||||
this.mockServer.expect(requestTo("/person/1"))
|
||||
.andExpect(header("Accept", "application/json"))
|
||||
.andRespond(withSuccess(RESPONSE_BODY, MediaType.APPLICATION_JSON));
|
||||
|
||||
this.restTemplate.getForObject(new URI("/person/1"), Person.class);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testStringContains() throws Exception {
|
||||
|
||||
this.mockServer.expect(requestTo("/person/1"))
|
||||
.andExpect(header("Accept", containsString("json")))
|
||||
.andRespond(withSuccess(RESPONSE_BODY, MediaType.APPLICATION_JSON));
|
||||
|
||||
this.restTemplate.getForObject(new URI("/person/1"), Person.class);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.samples.matchers;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.isIn;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.jsonPath;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Examples of defining expectations on JSON request content with
|
||||
* <a href="http://goessner.net/articles/JsonPath/">JSONPath</a> expressions.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class JsonPathRequestMatcherTests {
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private MultiValueMap<String, Person> people;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.people = new LinkedMultiValueMap<String, Person>();
|
||||
this.people.add("composers", new Person("Johann Sebastian Bach"));
|
||||
this.people.add("composers", new Person("Johannes Brahms"));
|
||||
this.people.add("composers", new Person("Edvard Grieg"));
|
||||
this.people.add("composers", new Person("Robert Schumann"));
|
||||
this.people.add("performers", new Person("Vladimir Ashkenazy"));
|
||||
this.people.add("performers", new Person("Yehudi Menuhin"));
|
||||
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new MappingJacksonHttpMessageConverter());
|
||||
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.restTemplate.setMessageConverters(converters);
|
||||
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExists() throws Exception {
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.composers[0]").exists())
|
||||
.andExpect(jsonPath("$.composers[1]").exists())
|
||||
.andExpect(jsonPath("$.composers[2]").exists())
|
||||
.andExpect(jsonPath("$.composers[3]").exists())
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotExist() throws Exception {
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.composers[?(@.name = 'Edvard Grieeeeeeg')]").doesNotExist())
|
||||
.andExpect(jsonPath("$.composers[?(@.name = 'Robert Schuuuuuuman')]").doesNotExist())
|
||||
.andExpect(jsonPath("$.composers[-1]").doesNotExist())
|
||||
.andExpect(jsonPath("$.composers[4]").doesNotExist())
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualTo() throws Exception {
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach"))
|
||||
.andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin"))
|
||||
.andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))) // Hamcrest
|
||||
.andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))) // Hamcrest
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHamcrestMatcher() throws Exception {
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.composers[0].name", startsWith("Johann")))
|
||||
.andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy")))
|
||||
.andExpect(jsonPath("$.performers[1].name", containsString("di Me")))
|
||||
.andExpect(jsonPath("$.composers[1].name", isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHamcrestMatcherWithParameterizedJsonPath() throws Exception {
|
||||
String composerName = "$.composers[%s].name";
|
||||
String performerName = "$.performers[%s].name";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath(composerName, 0).value(startsWith("Johann")))
|
||||
.andExpect(jsonPath(performerName, 0).value(endsWith("Ashkenazy")))
|
||||
.andExpect(jsonPath(performerName, 1).value(containsString("di Me")))
|
||||
.andExpect(jsonPath(composerName, 1).value(isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.samples.matchers;
|
||||
|
||||
import static org.hamcrest.Matchers.hasXPath;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Examples of defining expectations on XML request content with XMLUnit.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*
|
||||
* @see ContentRequestMatcherTests
|
||||
* @see XpathRequestMatcherTests
|
||||
*/
|
||||
public class XmlContentRequestMatcherTests {
|
||||
|
||||
private static final String PEOPLE_XML =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
|
||||
"<people><composers>" +
|
||||
"<composer><name>Johann Sebastian Bach</name><someBoolean>false</someBoolean><someDouble>21.0</someDouble></composer>" +
|
||||
"<composer><name>Johannes Brahms</name><someBoolean>false</someBoolean><someDouble>0.0025</someDouble></composer>" +
|
||||
"<composer><name>Edvard Grieg</name><someBoolean>false</someBoolean><someDouble>1.6035</someDouble></composer>" +
|
||||
"<composer><name>Robert Schumann</name><someBoolean>false</someBoolean><someDouble>NaN</someDouble></composer>" +
|
||||
"</composers></people>";
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private PeopleWrapper people;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
List<Person> composers = Arrays.asList(
|
||||
new Person("Johann Sebastian Bach").setSomeDouble(21),
|
||||
new Person("Johannes Brahms").setSomeDouble(.0025),
|
||||
new Person("Edvard Grieg").setSomeDouble(1.6035),
|
||||
new Person("Robert Schumann").setSomeDouble(Double.NaN));
|
||||
|
||||
this.people = new PeopleWrapper(composers);
|
||||
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.restTemplate.setMessageConverters(converters);
|
||||
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlEqualTo() throws Exception {
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(content().xml(PEOPLE_XML))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHamcrestNodeMatcher() throws Exception {
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(content().node(hasXPath("/people/composers/composer[1]")))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@XmlRootElement(name="people")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class PeopleWrapper {
|
||||
|
||||
@XmlElementWrapper(name="composers")
|
||||
@XmlElement(name="composer")
|
||||
private List<Person> composers;
|
||||
|
||||
public PeopleWrapper() {
|
||||
}
|
||||
|
||||
public PeopleWrapper(List<Person> composers) {
|
||||
this.composers = composers;
|
||||
}
|
||||
|
||||
public List<Person> getComposers() {
|
||||
return this.composers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.samples.matchers;
|
||||
|
||||
import static org.hamcrest.Matchers.closeTo;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.content;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.mock.client.match.RequestMatchers.xpath;
|
||||
import static org.springframework.test.web.mock.client.response.ResponseCreators.withSuccess;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Examples of defining expectations on XML request content with XPath expressions.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*
|
||||
* @see ContentRequestMatcherTests
|
||||
* @see XmlContentRequestMatcherTests
|
||||
*/
|
||||
public class XpathRequestMatcherTests {
|
||||
|
||||
private static final Map<String, String> NS =
|
||||
Collections.singletonMap("ns", "http://example.org/music/people");
|
||||
|
||||
private MockRestServiceServer mockServer;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private PeopleWrapper people;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
||||
List<Person> composers = Arrays.asList(
|
||||
new Person("Johann Sebastian Bach").setSomeDouble(21),
|
||||
new Person("Johannes Brahms").setSomeDouble(.0025),
|
||||
new Person("Edvard Grieg").setSomeDouble(1.6035),
|
||||
new Person("Robert Schumann").setSomeDouble(Double.NaN));
|
||||
|
||||
List<Person> performers = Arrays.asList(
|
||||
new Person("Vladimir Ashkenazy").setSomeBoolean(false),
|
||||
new Person("Yehudi Menuhin").setSomeBoolean(true));
|
||||
|
||||
this.people = new PeopleWrapper(composers, performers);
|
||||
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.restTemplate.setMessageConverters(converters);
|
||||
|
||||
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExists() throws Exception {
|
||||
|
||||
String composer = "/ns:people/composers/composer[%s]";
|
||||
String performer = "/ns:people/performers/performer[%s]";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath(composer, NS, 1).exists())
|
||||
.andExpect(xpath(composer, NS, 2).exists())
|
||||
.andExpect(xpath(composer, NS, 3).exists())
|
||||
.andExpect(xpath(composer, NS, 4).exists())
|
||||
.andExpect(xpath(performer, NS, 1).exists())
|
||||
.andExpect(xpath(performer, NS, 2).exists())
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotExist() throws Exception {
|
||||
|
||||
String composer = "/ns:people/composers/composer[%s]";
|
||||
String performer = "/ns:people/performers/performer[%s]";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath(composer, NS, 0).doesNotExist())
|
||||
.andExpect(xpath(composer, NS, 5).doesNotExist())
|
||||
.andExpect(xpath(performer, NS, 0).doesNotExist())
|
||||
.andExpect(xpath(performer, NS, 3).doesNotExist())
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
|
||||
String composerName = "/ns:people/composers/composer[%s]/name";
|
||||
String performerName = "/ns:people/performers/performer[%s]/name";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath(composerName, NS, 1).string("Johann Sebastian Bach"))
|
||||
.andExpect(xpath(composerName, NS, 2).string("Johannes Brahms"))
|
||||
.andExpect(xpath(composerName, NS, 3).string("Edvard Grieg"))
|
||||
.andExpect(xpath(composerName, NS, 4).string("Robert Schumann"))
|
||||
.andExpect(xpath(performerName, NS, 1).string("Vladimir Ashkenazy"))
|
||||
.andExpect(xpath(performerName, NS, 2).string("Yehudi Menuhin"))
|
||||
.andExpect(xpath(composerName, NS, 1).string(equalTo("Johann Sebastian Bach"))) // Hamcrest..
|
||||
.andExpect(xpath(composerName, NS, 1).string(startsWith("Johann"))) // Hamcrest..
|
||||
.andExpect(xpath(composerName, NS, 1).string(notNullValue())) // Hamcrest..
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumber() throws Exception {
|
||||
|
||||
String composerDouble = "/ns:people/composers/composer[%s]/someDouble";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath(composerDouble, NS, 1).number(21d))
|
||||
.andExpect(xpath(composerDouble, NS, 2).number(.0025))
|
||||
.andExpect(xpath(composerDouble, NS, 3).number(1.6035))
|
||||
.andExpect(xpath(composerDouble, NS, 4).number(Double.NaN))
|
||||
.andExpect(xpath(composerDouble, NS, 1).number(equalTo(21d))) // Hamcrest..
|
||||
.andExpect(xpath(composerDouble, NS, 3).number(closeTo(1.6, .01))) // Hamcrest..
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoolean() throws Exception {
|
||||
|
||||
String performerBooleanValue = "/ns:people/performers/performer[%s]/someBoolean";
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath(performerBooleanValue, NS, 1).booleanValue(false))
|
||||
.andExpect(xpath(performerBooleanValue, NS, 2).booleanValue(true))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeCount() throws Exception {
|
||||
|
||||
this.mockServer.expect(requestTo("/composers"))
|
||||
.andExpect(content().mimeType("application/xml"))
|
||||
.andExpect(xpath("/ns:people/composers/composer", NS).nodeCount(4))
|
||||
.andExpect(xpath("/ns:people/performers/performer", NS).nodeCount(2))
|
||||
.andExpect(xpath("/ns:people/composers/composer", NS).nodeCount(lessThan(5))) // Hamcrest..
|
||||
.andExpect(xpath("/ns:people/performers/performer", NS).nodeCount(greaterThan(0))) // Hamcrest..
|
||||
.andRespond(withSuccess());
|
||||
|
||||
this.restTemplate.put(new URI("/composers"), this.people);
|
||||
this.mockServer.verify();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@XmlRootElement(name="people", namespace="http://example.org/music/people")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class PeopleWrapper {
|
||||
|
||||
@XmlElementWrapper(name="composers")
|
||||
@XmlElement(name="composer")
|
||||
private List<Person> composers;
|
||||
|
||||
@XmlElementWrapper(name="performers")
|
||||
@XmlElement(name="performer")
|
||||
private List<Person> performers;
|
||||
|
||||
public PeopleWrapper() {
|
||||
}
|
||||
|
||||
public PeopleWrapper(List<Person> composers, List<Person> performers) {
|
||||
this.composers = composers;
|
||||
this.performers = performers;
|
||||
}
|
||||
|
||||
public List<Person> getComposers() {
|
||||
return this.composers;
|
||||
}
|
||||
|
||||
public List<Person> getPerformers() {
|
||||
return this.performers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* A stub implementation of the {@link MvcResult} contract.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class StubMvcResult implements MvcResult {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private Object handler;
|
||||
|
||||
private HandlerInterceptor[] interceptors;
|
||||
|
||||
private Exception resolvedException;
|
||||
|
||||
private ModelAndView mav;
|
||||
|
||||
private FlashMap flashMap;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
public StubMvcResult(MockHttpServletRequest request,
|
||||
Object handler,
|
||||
HandlerInterceptor[] interceptors,
|
||||
Exception resolvedException,
|
||||
ModelAndView mav,
|
||||
FlashMap flashMap,
|
||||
MockHttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.handler = handler;
|
||||
this.interceptors = interceptors;
|
||||
this.resolvedException = resolvedException;
|
||||
this.mav = mav;
|
||||
this.flashMap = flashMap;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public Object getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public HandlerInterceptor[] getInterceptors() {
|
||||
return interceptors;
|
||||
}
|
||||
|
||||
public Exception getResolvedException() {
|
||||
return resolvedException;
|
||||
}
|
||||
|
||||
public ModelAndView getModelAndView() {
|
||||
return mav;
|
||||
}
|
||||
|
||||
public FlashMap getFlashMap() {
|
||||
return flashMap;
|
||||
}
|
||||
|
||||
public MockHttpServletResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public ModelAndView getMav() {
|
||||
return mav;
|
||||
}
|
||||
|
||||
public void setMav(ModelAndView mav) {
|
||||
this.mav = mav;
|
||||
}
|
||||
|
||||
public void setRequest(MockHttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public void setHandler(Object handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public void setInterceptors(HandlerInterceptor[] interceptors) {
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
|
||||
public void setResolvedException(Exception resolvedException) {
|
||||
this.resolvedException = resolvedException;
|
||||
}
|
||||
|
||||
public void setFlashMap(FlashMap flashMap) {
|
||||
this.flashMap = flashMap;
|
||||
}
|
||||
|
||||
public void setResponse(MockHttpServletResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.mock.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.support.SessionFlashMapManager;
|
||||
|
||||
/**
|
||||
* Tests building a MockHttpServletRequest with {@link MockHttpServletRequestBuilder}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MockHttpServletRequestBuilderTests {
|
||||
|
||||
private MockHttpServletRequestBuilder builder;
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/foo/bar"), HttpMethod.GET);
|
||||
servletContext = new MockServletContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void method() {
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("GET", request.getMethod());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uri() throws Exception {
|
||||
URI uri = new URI("https://java.sun.com:8080/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)");
|
||||
this.builder = new MockHttpServletRequestBuilder(uri, HttpMethod.GET);
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("https", request.getScheme());
|
||||
assertEquals("foo=bar", request.getQueryString());
|
||||
assertEquals("java.sun.com", request.getServerName());
|
||||
assertEquals(8080, request.getServerPort());
|
||||
assertEquals("/javase/6/docs/api/java/util/BitSet.html", request.getRequestURI());
|
||||
assertEquals("https://java.sun.com:8080/javase/6/docs/api/java/util/BitSet.html",
|
||||
request.getRequestURL().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriEncodedPath() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/foo%20bar"), HttpMethod.GET);
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("/foo%20bar", request.getRequestURI());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathEmpty() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/foo"), HttpMethod.GET);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("", request.getContextPath());
|
||||
assertEquals("", request.getServletPath());
|
||||
assertEquals("/foo", request.getPathInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathServletPathEmpty() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/travel/hotels/42"), HttpMethod.GET);
|
||||
this.builder.contextPath("/travel");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("/travel", request.getContextPath());
|
||||
assertEquals("", request.getServletPath());
|
||||
assertEquals("/hotels/42", request.getPathInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathServletPath() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/travel/main/hotels/42"), HttpMethod.GET);
|
||||
this.builder.contextPath("/travel");
|
||||
this.builder.servletPath("/main");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("/travel", request.getContextPath());
|
||||
assertEquals("/main", request.getServletPath());
|
||||
assertEquals("/hotels/42", request.getPathInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathServletPathInfoEmpty() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/travel/hotels/42"), HttpMethod.GET);
|
||||
|
||||
this.builder.contextPath("/travel");
|
||||
this.builder.servletPath("/hotels/42");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("/travel", request.getContextPath());
|
||||
assertEquals("/hotels/42", request.getServletPath());
|
||||
assertNull(request.getPathInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathServletPathInfo() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/"), HttpMethod.GET);
|
||||
this.builder.servletPath("/index.html");
|
||||
this.builder.pathInfo(null);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("", request.getContextPath());
|
||||
assertEquals("/index.html", request.getServletPath());
|
||||
assertNull(request.getPathInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contextPathServletPathInvalid() throws Exception {
|
||||
|
||||
testContextPathServletPathInvalid("/Foo", "", "requestURI [/foo/bar] does not start with contextPath [/Foo]");
|
||||
testContextPathServletPathInvalid("foo", "", "Context path must start with a '/'");
|
||||
testContextPathServletPathInvalid("/foo/", "", "Context path must not end with a '/'");
|
||||
|
||||
testContextPathServletPathInvalid("/foo", "/Bar", "Invalid servletPath [/Bar] for requestURI [/foo/bar]");
|
||||
testContextPathServletPathInvalid("/foo", "bar", "Servlet path must start with a '/'");
|
||||
testContextPathServletPathInvalid("/foo", "/bar/", "Servlet path must not end with a '/'");
|
||||
}
|
||||
|
||||
private void testContextPathServletPathInvalid(String contextPath, String servletPath, String message) {
|
||||
try {
|
||||
this.builder.contextPath(contextPath);
|
||||
this.builder.servletPath(servletPath);
|
||||
this.builder.buildRequest(this.servletContext);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertEquals(message, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriAndFragment() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/foo#bar"), HttpMethod.GET);
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("/foo", request.getRequestURI());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParameter() {
|
||||
this.builder.param("foo", "bar", "baz");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
|
||||
assertArrayEquals(new String[]{"bar", "baz"}, parameterMap.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParameterFromQuery() throws Exception {
|
||||
this.builder = new MockHttpServletRequestBuilder(new URI("/?foo=bar&foo=baz"), HttpMethod.GET);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
|
||||
assertArrayEquals(new String[]{"bar", "baz"}, parameterMap.get("foo"));
|
||||
assertEquals("foo=bar&foo=baz", request.getQueryString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParametersFromQuery_i18n() throws Exception {
|
||||
URI uri = new URI("/?foo=I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n");
|
||||
this.builder = new MockHttpServletRequestBuilder(uri, HttpMethod.GET);
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n", request.getParameter("foo"));
|
||||
assertEquals("foo=I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n", request.getQueryString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptHeader() throws Exception {
|
||||
this.builder.accept(MediaType.TEXT_HTML, MediaType.APPLICATION_XML);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
List<String> accept = Collections.list(request.getHeaders("Accept"));
|
||||
List<MediaType> result = MediaType.parseMediaTypes(accept.get(0));
|
||||
|
||||
assertEquals(1, accept.size());
|
||||
assertEquals("text/html", result.get(0).toString());
|
||||
assertEquals("application/xml", result.get(1).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentType() throws Exception {
|
||||
this.builder.contentType(MediaType.TEXT_HTML);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
String contentType = request.getContentType();
|
||||
List<String> contentTypes = Collections.list(request.getHeaders("Content-Type"));
|
||||
|
||||
assertEquals("text/html", contentType);
|
||||
assertEquals(1, contentTypes.size());
|
||||
assertEquals("text/html", contentTypes.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void body() throws Exception {
|
||||
byte[] body = "Hello World".getBytes("UTF-8");
|
||||
this.builder.body(body);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
byte[] result = FileCopyUtils.copyToByteArray(request.getInputStream());
|
||||
|
||||
assertArrayEquals(body, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void header() throws Exception {
|
||||
this.builder.header("foo", "bar", "baz");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
List<String> headers = Collections.list(request.getHeaders("foo"));
|
||||
|
||||
assertEquals(2, headers.size());
|
||||
assertEquals("bar", headers.get(0));
|
||||
assertEquals("baz", headers.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headers() throws Exception {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
httpHeaders.put("foo", Arrays.asList("bar", "baz"));
|
||||
this.builder.headers(httpHeaders);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
List<String> headers = Collections.list(request.getHeaders("foo"));
|
||||
|
||||
assertEquals(2, headers.size());
|
||||
assertEquals("bar", headers.get(0));
|
||||
assertEquals("baz", headers.get(1));
|
||||
assertEquals(MediaType.APPLICATION_JSON.toString(), request.getHeader("Content-Type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cookie() throws Exception {
|
||||
Cookie cookie1 = new Cookie("foo", "bar");
|
||||
Cookie cookie2 = new Cookie("baz", "qux");
|
||||
this.builder.cookie(cookie1, cookie2);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
Cookie[] cookies = request.getCookies();
|
||||
|
||||
assertEquals(2, cookies.length);
|
||||
assertEquals("foo", cookies[0].getName());
|
||||
assertEquals("bar", cookies[0].getValue());
|
||||
assertEquals("baz", cookies[1].getName());
|
||||
assertEquals("qux", cookies[1].getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locale() throws Exception {
|
||||
Locale locale = new Locale("nl", "nl");
|
||||
this.builder.locale(locale);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals(locale, request.getLocale());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void characterEncoding() throws Exception {
|
||||
String encoding = "UTF-8";
|
||||
this.builder.characterEncoding(encoding);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals(encoding, request.getCharacterEncoding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestAttribute() throws Exception {
|
||||
this.builder.requestAttr("foo", "bar");
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("bar", request.getAttribute("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionAttribute() throws Exception {
|
||||
this.builder.sessionAttr("foo", "bar");
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("bar", request.getSession().getAttribute("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sessionAttributes() throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("foo", "bar");
|
||||
this.builder.sessionAttrs(map);
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals("bar", request.getSession().getAttribute("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void session() throws Exception {
|
||||
MockHttpSession session = new MockHttpSession(this.servletContext);
|
||||
session.setAttribute("foo", "bar");
|
||||
this.builder.session(session);
|
||||
this.builder.sessionAttr("baz", "qux");
|
||||
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals(session, request.getSession());
|
||||
assertEquals("bar", request.getSession().getAttribute("foo"));
|
||||
assertEquals("qux", request.getSession().getAttribute("baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flashAttribute() throws Exception {
|
||||
this.builder.flashAttr("foo", "bar");
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
FlashMap flashMap = new SessionFlashMapManager().retrieveAndUpdate(request, null);
|
||||
assertNotNull(flashMap);
|
||||
assertEquals("bar", flashMap.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void principal() throws Exception {
|
||||
User user = new User();
|
||||
this.builder.principal(user);
|
||||
MockHttpServletRequest request = this.builder.buildRequest(this.servletContext);
|
||||
|
||||
assertEquals(user, request.getUserPrincipal());
|
||||
}
|
||||
|
||||
|
||||
private final class User implements Principal {
|
||||
|
||||
public String getName() {
|
||||
return "Foo";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.ContentResultMatchers;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ContentResultMatchersTests {
|
||||
|
||||
@Test
|
||||
public void typeMatches() throws Exception {
|
||||
new ContentResultMatchers().mimeType("application/json;charset=UTF-8").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void typeNoMatch() throws Exception {
|
||||
new ContentResultMatchers().mimeType("text/plain").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encoding() throws Exception {
|
||||
new ContentResultMatchers().encoding("UTF-8").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void encodingNoMatch() throws Exception {
|
||||
new ContentResultMatchers().encoding("ISO-8859-1").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string() throws Exception {
|
||||
new ContentResultMatchers().string(new String(CONTENT.getBytes("UTF-8"))).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void stringNoMatch() throws Exception {
|
||||
new ContentResultMatchers().encoding("bogus").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringMatcher() throws Exception {
|
||||
String content = new String(CONTENT.getBytes("UTF-8"));
|
||||
new ContentResultMatchers().string(Matchers.equalTo(content)).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void stringMatcherNoMatch() throws Exception {
|
||||
new ContentResultMatchers().string(Matchers.equalTo("bogus")).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bytes() throws Exception {
|
||||
new ContentResultMatchers().bytes(CONTENT.getBytes("UTF-8")).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void bytesNoMatch() throws Exception {
|
||||
new ContentResultMatchers().bytes("bogus".getBytes()).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
|
||||
private static final String CONTENT = "{\"foo\":\"bar\"}";
|
||||
|
||||
private StubMvcResult getStubMvcResult() throws Exception {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.addHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
response.getWriter().print(new String(CONTENT.getBytes("UTF-8")));
|
||||
return new StubMvcResult(null, null, null, null, null, null, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.junit.Test;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.FlashAttributeResultMatchers;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
|
||||
/**
|
||||
* @author Craig Walls
|
||||
*/
|
||||
public class FlashAttributeResultMatchersTests {
|
||||
|
||||
@Test
|
||||
public void attributeExists() throws Exception {
|
||||
new FlashAttributeResultMatchers().attributeExists("good").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeExists_doesntExist() throws Exception {
|
||||
new FlashAttributeResultMatchers().attributeExists("bad").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attribute() throws Exception {
|
||||
new FlashAttributeResultMatchers().attribute("good", "good").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attribute_incorrectValue() throws Exception {
|
||||
new FlashAttributeResultMatchers().attribute("good", "not good").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
private StubMvcResult getStubMvcResult() {
|
||||
FlashMap flashMap = new FlashMap();
|
||||
flashMap.put("good", "good");
|
||||
StubMvcResult mvcResult = new StubMvcResult(null, null, null, null, null, flashMap, null);
|
||||
return mvcResult;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.JsonPathResultMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link JsonPathResultMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class JsonPathResultMatchersTests {
|
||||
|
||||
@Test
|
||||
public void value() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").value("bar").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void valueNoMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").value("bogus").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueMatcher() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").value(Matchers.equalTo("bar")).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void valueMatcherNoMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").value(Matchers.equalTo("bogus")).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exists() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").exists().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void existsNoMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.bogus").exists().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotExist() throws Exception {
|
||||
new JsonPathResultMatchers("$.bogus").doesNotExist().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void doesNotExistNoMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.foo").doesNotExist().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isArrayMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.qux").isArray().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void isArrayNoMatch() throws Exception {
|
||||
new JsonPathResultMatchers("$.bar").isArray().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
|
||||
private static final String RESPONSE_CONTENT = "{\"foo\":\"bar\", \"qux\":[\"baz1\",\"baz2\"]}";
|
||||
|
||||
private StubMvcResult getStubMvcResult() throws Exception {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.addHeader("Content-Type", "application/json");
|
||||
response.getWriter().print(new String(RESPONSE_CONTENT.getBytes("ISO-8859-1")));
|
||||
return new StubMvcResult(null, null, null, null, null, null, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.is;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.ModelResultMatchers;
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* @author Craig Walls
|
||||
*/
|
||||
public class ModelResultMatchersTests {
|
||||
|
||||
private ModelResultMatchers matchers;
|
||||
|
||||
private MvcResult mvcResult;
|
||||
private MvcResult mvcResultWithError;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.matchers = new ModelResultMatchers();
|
||||
|
||||
ModelAndView mav = new ModelAndView("view", "good", "good");
|
||||
BindingResult bindingResult = new BeanPropertyBindingResult("good", "good");
|
||||
mav.addObject(BindingResult.MODEL_KEY_PREFIX + "good", bindingResult);
|
||||
|
||||
this.mvcResult = getMvcResult(mav);
|
||||
|
||||
Date date = new Date();
|
||||
BindingResult bindingResultWithError = new BeanPropertyBindingResult(date, "date");
|
||||
bindingResultWithError.rejectValue("time", "error");
|
||||
|
||||
ModelAndView mavWithError = new ModelAndView("view", "good", "good");
|
||||
mavWithError.addObject("date", date);
|
||||
mavWithError.addObject(BindingResult.MODEL_KEY_PREFIX + "date", bindingResultWithError);
|
||||
|
||||
this.mvcResultWithError = getMvcResult(mavWithError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attributeExists() throws Exception {
|
||||
this.matchers.attributeExists("good").match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeExists_doesNotExist() throws Exception {
|
||||
this.matchers.attributeExists("bad").match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attribute_equal() throws Exception {
|
||||
this.matchers.attribute("good", is("good")).match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attribute_notEqual() throws Exception {
|
||||
this.matchers.attribute("good", is("bad")).match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasNoErrors() throws Exception {
|
||||
this.matchers.hasNoErrors().match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void hasNoErrors_withErrors() throws Exception {
|
||||
this.matchers.hasNoErrors().match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attributeHasErrors() throws Exception {
|
||||
this.matchers.attributeHasErrors("date").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasErrors_withoutErrors() throws Exception {
|
||||
this.matchers.attributeHasErrors("good").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attributeHasNoErrors() throws Exception {
|
||||
this.matchers.attributeHasNoErrors("good").match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasNoErrors_withoutAttribute() throws Exception {
|
||||
this.matchers.attributeHasNoErrors("missing").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasNoErrors_withErrors() throws Exception {
|
||||
this.matchers.attributeHasNoErrors("date").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attributeHasFieldErrors() throws Exception {
|
||||
this.matchers.attributeHasFieldErrors("date", "time").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasFieldErrors_withoutAttribute() throws Exception {
|
||||
this.matchers.attributeHasFieldErrors("missing", "bad").match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasFieldErrors_withoutErrorsForAttribute() throws Exception {
|
||||
this.matchers.attributeHasFieldErrors("date", "time").match(this.mvcResult);
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void attributeHasFieldErrors_withoutErrorsForField() throws Exception {
|
||||
this.matchers.attributeHasFieldErrors("date", "good", "time").match(this.mvcResultWithError);
|
||||
}
|
||||
|
||||
private MvcResult getMvcResult(ModelAndView modelAndView) {
|
||||
return new StubMvcResult(null, null, null, null, modelAndView, null, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.PrintingResultHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.FlashMap;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Tests for {@link PrintingResultHandler}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class PrintingResultHandlerTests {
|
||||
|
||||
private TestPrintingResultHandler handler;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
private StubMvcResult mvcResult;
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.handler = new TestPrintingResultHandler();
|
||||
this.request = new MockHttpServletRequest("GET", "/");
|
||||
this.response = new MockHttpServletResponse();
|
||||
this.mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintRequest() throws Exception {
|
||||
this.request.addParameter("param", "paramValue");
|
||||
this.request.addHeader("header", "headerValue");
|
||||
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("header", "headerValue");
|
||||
|
||||
assertValue("MockHttpServletRequest", "HTTP Method", this.request.getMethod());
|
||||
assertValue("MockHttpServletRequest", "Request URI", this.request.getRequestURI());
|
||||
assertValue("MockHttpServletRequest", "Parameters", this.request.getParameterMap());
|
||||
assertValue("MockHttpServletRequest", "Headers", headers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintResponse() throws Exception {
|
||||
this.response.setStatus(400, "error");
|
||||
this.response.addHeader("header", "headerValue");
|
||||
this.response.setContentType("text/plain");
|
||||
this.response.getWriter().print("content");
|
||||
this.response.setForwardedUrl("redirectFoo");
|
||||
this.response.sendRedirect("/redirectFoo");
|
||||
this.response.addCookie(new Cookie("cookie", "cookieValue"));
|
||||
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("header", "headerValue");
|
||||
headers.setContentType(MediaType.TEXT_PLAIN);
|
||||
headers.setLocation(new URI("/redirectFoo"));
|
||||
|
||||
assertValue("MockHttpServletResponse", "Status", this.response.getStatus());
|
||||
assertValue("MockHttpServletResponse", "Error message", response.getErrorMessage());
|
||||
assertValue("MockHttpServletResponse", "Headers", headers);
|
||||
assertValue("MockHttpServletResponse", "Content type", this.response.getContentType());
|
||||
assertValue("MockHttpServletResponse", "Body", this.response.getContentAsString());
|
||||
assertValue("MockHttpServletResponse", "Forwarded URL", this.response.getForwardedUrl());
|
||||
assertValue("MockHttpServletResponse", "Redirected URL", this.response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintHandlerNull() throws Exception {
|
||||
StubMvcResult mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response);
|
||||
this.handler.handle(mvcResult);
|
||||
|
||||
assertValue("Handler", "Type", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintHandler() throws Exception {
|
||||
this.mvcResult.setHandler(new Object());
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("Handler", "Type", Object.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintHandlerMethod() throws Exception {
|
||||
HandlerMethod handlerMethod = new HandlerMethod(this, "handle");
|
||||
this.mvcResult.setHandler(handlerMethod);
|
||||
this.handler.handle(mvcResult);
|
||||
|
||||
assertValue("Handler", "Type", this.getClass().getName());
|
||||
assertValue("Handler", "Method", handlerMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolvedExceptionNull() throws Exception {
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("Resolved Exception", "Type", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolvedException() throws Exception {
|
||||
this.mvcResult.setResolvedException(new Exception());
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("Resolved Exception", "Type", Exception.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModelAndViewNull() throws Exception {
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("ModelAndView", "View name", null);
|
||||
assertValue("ModelAndView", "View", null);
|
||||
assertValue("ModelAndView", "Model", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModelAndView() throws Exception {
|
||||
BindException bindException = new BindException(new Object(), "target");
|
||||
bindException.reject("errorCode");
|
||||
|
||||
ModelAndView mav = new ModelAndView("viewName");
|
||||
mav.addObject("attrName", "attrValue");
|
||||
mav.addObject(BindingResult.MODEL_KEY_PREFIX + "attrName", bindException);
|
||||
|
||||
this.mvcResult.setMav(mav);
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("ModelAndView", "View name", "viewName");
|
||||
assertValue("ModelAndView", "View", null);
|
||||
assertValue("ModelAndView", "Attribute", "attrName");
|
||||
assertValue("ModelAndView", "value", "attrValue");
|
||||
assertValue("ModelAndView", "errors", bindException.getAllErrors());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlashMapNull() throws Exception {
|
||||
this.handler.handle(mvcResult);
|
||||
|
||||
assertValue("FlashMap", "Type", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlashMap() throws Exception {
|
||||
FlashMap flashMap = new FlashMap();
|
||||
flashMap.put("attrName", "attrValue");
|
||||
this.request.setAttribute(DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP", flashMap);
|
||||
|
||||
this.handler.handle(this.mvcResult);
|
||||
|
||||
assertValue("FlashMap", "Attribute", "attrName");
|
||||
assertValue("FlashMap", "value", "attrValue");
|
||||
}
|
||||
|
||||
private void assertValue(String heading, String label, Object value) {
|
||||
Map<String, Map<String, Object>> printedValues = this.handler.getPrinter().printedValues;
|
||||
assertTrue("Heading " + heading + " not printed", printedValues.containsKey(heading));
|
||||
assertEquals(value, printedValues.get(heading).get(label));
|
||||
}
|
||||
|
||||
|
||||
private static class TestPrintingResultHandler extends PrintingResultHandler {
|
||||
|
||||
public TestPrintingResultHandler() {
|
||||
super(new TestResultValuePrinter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestResultValuePrinter getPrinter() {
|
||||
return (TestResultValuePrinter) super.getPrinter();
|
||||
}
|
||||
|
||||
private static class TestResultValuePrinter implements ResultValuePrinter {
|
||||
|
||||
private String printedHeading;
|
||||
|
||||
private Map<String, Map<String, Object>> printedValues = new HashMap<String, Map<String, Object>>();
|
||||
|
||||
public void printHeading(String heading) {
|
||||
this.printedHeading = heading;
|
||||
this.printedValues.put(heading, new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
public void printValue(String label, Object value) {
|
||||
Assert.notNull(this.printedHeading,
|
||||
"Heading not printed before label " + label + " with value " + value);
|
||||
this.printedValues.get(this.printedHeading).put(label, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handle() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.StatusResultMatchers;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Tests for {@link StatusResultMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class StatusResultMatchersTests {
|
||||
|
||||
@Test
|
||||
public void testHttpStatusCodeResultMatchers() throws Exception {
|
||||
|
||||
StatusResultMatchers resultMatchers = new StatusResultMatchers();
|
||||
|
||||
List<AssertionError> failures = new ArrayList<AssertionError>();
|
||||
|
||||
for(HttpStatus status : HttpStatus.values()) {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(status.value());
|
||||
|
||||
String methodName = statusToMethodName(status);
|
||||
Method method = StatusResultMatchers.class.getMethod(methodName);
|
||||
try {
|
||||
ResultMatcher matcher = (ResultMatcher) ReflectionUtils.invokeMethod(method, resultMatchers);
|
||||
try {
|
||||
MvcResult mvcResult = new StubMvcResult(new MockHttpServletRequest(), null, null, null, null, null, response);
|
||||
matcher.match(mvcResult);
|
||||
}
|
||||
catch (AssertionError error) {
|
||||
failures.add(error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new Exception("Failed to obtain ResultMatcher: " + method.toString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!failures.isEmpty()) {
|
||||
fail("Failed status codes: " + failures);
|
||||
}
|
||||
}
|
||||
|
||||
private String statusToMethodName(HttpStatus status) throws NoSuchMethodException {
|
||||
String name = status.name().toLowerCase().replace("_", "-");
|
||||
return "is" + StringUtils.capitalize(Conventions.attributeNameToPropertyName(name));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.web.mock.servlet.StubMvcResult;
|
||||
import org.springframework.test.web.mock.servlet.result.XpathResultMatchers;
|
||||
|
||||
/**
|
||||
* Tests for {@link XpathResultMatchers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class XpathResultMatchersTests {
|
||||
|
||||
@Test
|
||||
public void testNodeMatcher() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).node(Matchers.notNullValue()).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNodeMatcherNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).node(Matchers.nullValue()).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExists() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).exists().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testExistsNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/Bar", null).exists().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotExist() throws Exception {
|
||||
new XpathResultMatchers("/foo/Bar", null).doesNotExist().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testDoesNotExistNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).doesNotExist().match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNodeCount() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).nodeCount(2).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNodeCountNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar", null).nodeCount(1).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[1]", null).string("111").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testStringNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[1]", null).string("112").match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumber() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[1]", null).number(111.0).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testNumberNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[1]", null).number(111.1).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoolean() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[2]", null).booleanValue(true).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
@Test(expected=AssertionError.class)
|
||||
public void testBooleanNoMatch() throws Exception {
|
||||
new XpathResultMatchers("/foo/bar[2]", null).booleanValue(false).match(getStubMvcResult());
|
||||
}
|
||||
|
||||
|
||||
private static final String RESPONSE_CONTENT = "<foo><bar>111</bar><bar>true</bar></foo>";
|
||||
|
||||
private StubMvcResult getStubMvcResult() throws Exception {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.addHeader("Content-Type", "application/json");
|
||||
response.getWriter().print(new String(RESPONSE_CONTENT.getBytes("ISO-8859-1")));
|
||||
return new StubMvcResult(null, null, null, null, null, null, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.FileSystemResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.mock.web.MockRequestDispatcher;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.support.AbstractContextLoader;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
* This class is here temporarily until the TestContext framework provides
|
||||
* support for WebApplicationContext yet:
|
||||
*
|
||||
* https://jira.springsource.org/browse/SPR-5243
|
||||
*
|
||||
* <p>After that this class will no longer be needed. It's provided here as an example
|
||||
* and to serve as a temporary solution.
|
||||
*/
|
||||
public class GenericWebContextLoader extends AbstractContextLoader {
|
||||
protected final MockServletContext servletContext;
|
||||
|
||||
public GenericWebContextLoader(String warRootDir, boolean isClasspathRelative) {
|
||||
ResourceLoader resourceLoader = isClasspathRelative ? new DefaultResourceLoader() : new FileSystemResourceLoader();
|
||||
this.servletContext = initServletContext(warRootDir, resourceLoader);
|
||||
}
|
||||
|
||||
private MockServletContext initServletContext(String warRootDir, ResourceLoader resourceLoader) {
|
||||
return new MockServletContext(warRootDir, resourceLoader) {
|
||||
// Required for DefaultServletHttpRequestHandler...
|
||||
public RequestDispatcher getNamedDispatcher(String path) {
|
||||
return (path.equals("default")) ? new MockRequestDispatcher(path) : super.getNamedDispatcher(path);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext();
|
||||
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
|
||||
prepareContext(context);
|
||||
loadBeanDefinitions(context, mergedConfig);
|
||||
return context;
|
||||
}
|
||||
|
||||
public ApplicationContext loadContext(String... locations) throws Exception {
|
||||
// should never be called
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected void prepareContext(GenericWebApplicationContext context) {
|
||||
this.servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
|
||||
context.setServletContext(this.servletContext);
|
||||
}
|
||||
|
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, String[] locations) {
|
||||
new XmlBeanDefinitionReader(context).loadBeanDefinitions(locations);
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
|
||||
context.refresh();
|
||||
context.registerShutdownHook();
|
||||
}
|
||||
|
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
new AnnotatedBeanDefinitionReader(context).register(mergedConfig.getClasses());
|
||||
loadBeanDefinitions(context, mergedConfig.getLocations());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResourceSuffix() {
|
||||
return "-context.xml";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Tests with Java configuration.
|
||||
*
|
||||
* The TestContext framework doesn't support WebApplicationContext yet:
|
||||
* https://jira.springsource.org/browse/SPR-5243
|
||||
*
|
||||
* A custom {@link ContextLoader} is used to load the WebApplicationContext.
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(loader=WebContextLoader.class, classes={WebConfig.class})
|
||||
public class JavaTestContextTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tilesDefinitions() throws Exception {
|
||||
this.mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("/WEB-INF/layouts/standardLayout.jsp"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextRepository;
|
||||
import org.springframework.test.web.mock.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
/**
|
||||
* Demonstrates how to use a {@link RequestPostProcessor} to add
|
||||
* request-building methods for establishing a security context for Spring
|
||||
* Security. While these are just examples,
|
||||
* <a href="https://jira.springsource.org/browse/SEC-2015">official support</a>
|
||||
* for Spring Security is planned.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
final class SecurityRequestPostProcessors {
|
||||
|
||||
/**
|
||||
* Establish a security context for a user with the specified username. All
|
||||
* details are declarative and do not require that the user actually exists.
|
||||
* This means that the authorities or roles need to be specified too.
|
||||
*/
|
||||
public static UserRequestPostProcessor user(String username) {
|
||||
return new UserRequestPostProcessor(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a security context for a user with the specified username. The
|
||||
* additional details are obtained from the {@link UserDetailsService}
|
||||
* declared in the {@link WebApplicationContext}.
|
||||
*/
|
||||
public static UserDetailsRequestPostProcessor userDeatilsService(String username) {
|
||||
return new UserDetailsRequestPostProcessor(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a security context with the given {@link SecurityContext} and
|
||||
* thus be authenticated with {@link SecurityContext#getAuthentication()}.
|
||||
*/
|
||||
public SecurityContextRequestPostProcessor securityContext(SecurityContext securityContext) {
|
||||
return new SecurityContextRequestPostProcessor(securityContext);
|
||||
}
|
||||
|
||||
|
||||
/** Support class for {@link RequestPostProcessor}'s that establish a Spring Security context */
|
||||
private static abstract class SecurityContextRequestPostProcessorSupport {
|
||||
|
||||
private SecurityContextRepository repository = new HttpSessionSecurityContextRepository();
|
||||
|
||||
final void save(Authentication authentication, HttpServletRequest request) {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(authentication);
|
||||
save(securityContext, request);
|
||||
}
|
||||
|
||||
final void save(SecurityContext securityContext, HttpServletRequest request) {
|
||||
HttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response);
|
||||
this.repository.loadContext(requestResponseHolder);
|
||||
|
||||
request = requestResponseHolder.getRequest();
|
||||
response = requestResponseHolder.getResponse();
|
||||
|
||||
this.repository.saveContext(securityContext, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public final static class SecurityContextRequestPostProcessor
|
||||
extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {
|
||||
|
||||
private final SecurityContext securityContext;
|
||||
|
||||
private SecurityContextRequestPostProcessor(SecurityContext securityContext) {
|
||||
this.securityContext = securityContext;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
save(this.securityContext,request);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
public final static class UserRequestPostProcessor
|
||||
extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {
|
||||
|
||||
private final String username;
|
||||
|
||||
private String rolePrefix = "ROLE_";
|
||||
|
||||
private Object credentials;
|
||||
|
||||
private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||
|
||||
private UserRequestPostProcessor(String username) {
|
||||
Assert.notNull(username, "username cannot be null");
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefix to append to each role if the role does not already start with
|
||||
* the prefix. If no prefix is desired, an empty String or null can be used.
|
||||
*/
|
||||
public UserRequestPostProcessor rolePrefix(String rolePrefix) {
|
||||
this.rolePrefix = rolePrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the roles of the user to authenticate as. This method is similar to
|
||||
* {@link #authorities(GrantedAuthority...)}, but just not as flexible.
|
||||
*
|
||||
* @param roles The roles to populate. Note that if the role does not start with
|
||||
* {@link #rolePrefix(String)} it will automatically be prepended. This means by
|
||||
* default {@code roles("ROLE_USER")} and {@code roles("USER")} are equivalent.
|
||||
* @see #authorities(GrantedAuthority...)
|
||||
* @see #rolePrefix(String)
|
||||
*/
|
||||
public UserRequestPostProcessor roles(String... roles) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(roles.length);
|
||||
for(String role : roles) {
|
||||
if(this.rolePrefix == null || role.startsWith(this.rolePrefix)) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
} else {
|
||||
authorities.add(new SimpleGrantedAuthority(this.rolePrefix + role));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the user's {@link GrantedAuthority}'s.
|
||||
* @param authorities
|
||||
* @see #roles(String...)
|
||||
*/
|
||||
public UserRequestPostProcessor authorities(GrantedAuthority... authorities) {
|
||||
this.authorities = Arrays.asList(authorities);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(this.username, this.credentials, this.authorities);
|
||||
save(authentication,request);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
public final static class UserDetailsRequestPostProcessor
|
||||
extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {
|
||||
|
||||
private final String username;
|
||||
|
||||
private String userDetailsServiceBeanId;
|
||||
|
||||
private UserDetailsRequestPostProcessor(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to specify the bean id of the {@link UserDetailsService} to
|
||||
* use to look up the {@link UserDetails}.
|
||||
*
|
||||
* <p>By default a lookup of {@link UserDetailsService} is performed by type. This
|
||||
* can be problematic if multiple {@link UserDetailsService} beans are declared.
|
||||
*/
|
||||
public UserDetailsRequestPostProcessor userDetailsServiceBeanId(String userDetailsServiceBeanId) {
|
||||
this.userDetailsServiceBeanId = userDetailsServiceBeanId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
UsernamePasswordAuthenticationToken authentication = authentication(request.getServletContext());
|
||||
save(authentication,request);
|
||||
return request;
|
||||
}
|
||||
|
||||
private UsernamePasswordAuthenticationToken authentication(ServletContext servletContext) {
|
||||
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
|
||||
UserDetailsService userDetailsService = userDetailsService(context);
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(this.username);
|
||||
return new UsernamePasswordAuthenticationToken(
|
||||
userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
private UserDetailsService userDetailsService(ApplicationContext context) {
|
||||
if(this.userDetailsServiceBeanId == null) {
|
||||
return context.getBean(UserDetailsService.class);
|
||||
}
|
||||
return context.getBean(this.userDetailsServiceBeanId, UserDetailsService.class);
|
||||
}
|
||||
}
|
||||
|
||||
private SecurityRequestPostProcessors() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.samples.context.SecurityRequestPostProcessors.user;
|
||||
import static org.springframework.test.web.mock.servlet.samples.context.SecurityRequestPostProcessors.userDeatilsService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.MvcResult;
|
||||
import org.springframework.test.web.mock.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.mock.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.mock.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Basic example that includes Spring Security configuration.
|
||||
*
|
||||
* <p>Note that currently there are no {@link ResultMatcher}' built specifically
|
||||
* for asserting the Spring Security context. However, it's quite easy to put
|
||||
* them together as shown below and Spring Security extensions will become
|
||||
* available in the near future.
|
||||
*
|
||||
* <p>This also demonstrates a custom {@link RequestPostProcessor} which authenticates
|
||||
* a user to a particular {@link HttpServletRequest}.
|
||||
*
|
||||
* <p>Also see the Javadoc of {@link GenericWebContextLoader}, a class that
|
||||
* provides temporary support for loading WebApplicationContext by extending
|
||||
* the TestContext framework.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Rossen Stoyanchev
|
||||
* @see SecurityRequestPostProcessors
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(
|
||||
loader=WebContextLoader.class,
|
||||
value={
|
||||
"classpath:org/springframework/test/web/mock/servlet/samples/context/security.xml",
|
||||
"classpath:org/springframework/test/web/mock/servlet/samples/servlet-context.xml"
|
||||
})
|
||||
public class SpringSecurityTests {
|
||||
|
||||
private static String SEC_CONTEXT_ATTR = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
|
||||
|
||||
@Autowired
|
||||
private FilterChainProxy springSecurityFilterChain;
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
|
||||
.addFilters(this.springSecurityFilterChain).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requiresAuthentication() throws Exception {
|
||||
mockMvc.perform(get("/user"))
|
||||
.andExpect(redirectedUrl("http://localhost/spring_security_login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessGranted() throws Exception {
|
||||
this.mockMvc.perform(get("/").with(userDeatilsService("user")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("/WEB-INF/layouts/standardLayout.jsp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessDenied() throws Exception {
|
||||
this.mockMvc.perform(get("/").with(user("user").roles("DENIED")))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userAuthenticates() throws Exception {
|
||||
final String username = "user";
|
||||
mockMvc.perform(post("/j_spring_security_check").param("j_username", username).param("j_password", "password"))
|
||||
.andExpect(redirectedUrl("/"))
|
||||
.andExpect(new ResultMatcher() {
|
||||
public void match(MvcResult mvcResult) throws Exception {
|
||||
HttpSession session = mvcResult.getRequest().getSession();
|
||||
SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR);
|
||||
Assert.assertEquals(securityContext.getAuthentication().getName(), username);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userAuthenticateFails() throws Exception {
|
||||
final String username = "user";
|
||||
mockMvc.perform(post("/j_spring_security_check").param("j_username", username).param("j_password", "invalid"))
|
||||
.andExpect(redirectedUrl("/spring_security_login?login_error"))
|
||||
.andExpect(new ResultMatcher() {
|
||||
public void match(MvcResult mvcResult) throws Exception {
|
||||
HttpSession session = mvcResult.getRequest().getSession();
|
||||
SecurityContext securityContext = (SecurityContext) session.getAttribute(SEC_CONTEXT_ATTR);
|
||||
Assert.assertNull(securityContext);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
import org.springframework.web.servlet.view.tiles2.TilesConfigurer;
|
||||
import org.springframework.web.servlet.view.tiles2.TilesView;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("home");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UrlBasedViewResolver urlBasedViewResolver() {
|
||||
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
|
||||
resolver.setViewClass(TilesView.class);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TilesConfigurer tilesConfigurer() {
|
||||
TilesConfigurer configurer = new TilesConfigurer();
|
||||
configurer.setDefinitions(new String[] {"/WEB-INF/**/tiles.xml"});
|
||||
return configurer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
class WebContextLoader extends GenericWebContextLoader {
|
||||
|
||||
public WebContextLoader() {
|
||||
super("src/test/resources/META-INF/web-resources", false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.samples.context;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Tests with XML configuration.
|
||||
*
|
||||
* The TestContext framework doesn't support WebApplicationContext yet:
|
||||
* https://jira.springsource.org/browse/SPR-5243
|
||||
*
|
||||
* A custom {@link ContextLoader} is used to load the WebApplicationContext.
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(
|
||||
loader=WebContextLoader.class,
|
||||
locations={"/org/springframework/test/web/mock/servlet/samples/servlet-context.xml"})
|
||||
public class XmlTestContextTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tilesDefinitions() throws Exception {
|
||||
this.mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("/WEB-INF/layouts/standardLayout.jsp"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.request;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
/**
|
||||
* Tests with asynchronous request handling.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class AsyncTests {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = standaloneSetup(new AsyncController()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeferredResult() throws Exception {
|
||||
this.mockMvc.perform(get("/1").param("deferredResult", "true"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(request().asyncStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallable() throws Exception {
|
||||
this.mockMvc.perform(get("/1").param("callable", "true"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(request().asyncStarted())
|
||||
.andExpect(request().asyncResult(new Person("Joe")));
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class AsyncController {
|
||||
|
||||
@RequestMapping(value="/{id}", params="deferredResult", produces="application/json")
|
||||
public DeferredResult<Person> getDeferredResult() {
|
||||
return new DeferredResult<Person>();
|
||||
}
|
||||
|
||||
@RequestMapping(value="/{id}", params="callable", produces="application/json")
|
||||
public Callable<Person> getCallable() {
|
||||
return new Callable<Person>() {
|
||||
public Person call() throws Exception {
|
||||
Thread.sleep(100);
|
||||
return new Person("Joe");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* Exception handling via {@code @ExceptionHandler} method.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionHandlerMethod() throws Exception {
|
||||
standaloneSetup(new PersonController()).build()
|
||||
.perform(get("/person/Clyde"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("errorView"));
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class PersonController {
|
||||
|
||||
@RequestMapping(value="/person/{name}", method=RequestMethod.GET)
|
||||
public String show(@PathVariable String name) {
|
||||
if (name.equals("Clyde")) {
|
||||
throw new IllegalArgumentException("Black listed");
|
||||
}
|
||||
return "person/show";
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
public String handleException(IllegalArgumentException exception) {
|
||||
return "errorView";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.flash;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.model;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
/**
|
||||
* Tests with {@link Filter}'s.
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class FilterTests {
|
||||
|
||||
@Test
|
||||
public void whenFiltersCompleteMvcProcessesRequest() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilters(new ContinueFilter()).build()
|
||||
.perform(post("/persons").param("name", "Andy"))
|
||||
.andExpect(status().isMovedTemporarily())
|
||||
.andExpect(redirectedUrl("/person/1"))
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("id"))
|
||||
.andExpect(flash().attributeCount(1))
|
||||
.andExpect(flash().attribute("message", "success!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filtersProcessRequest() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilters(new ContinueFilter(), new RedirectFilter()).build()
|
||||
.perform(post("/persons").param("name", "Andy"))
|
||||
.andExpect(redirectedUrl("/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterMappedBySuffix() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilter(new RedirectFilter(), "*.html").build()
|
||||
.perform(post("/persons.html").param("name", "Andy"))
|
||||
.andExpect(redirectedUrl("/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWithExactMapping() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilter(new RedirectFilter(), "/p", "/persons").build()
|
||||
.perform(post("/persons").param("name", "Andy"))
|
||||
.andExpect(redirectedUrl("/login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterSkipped() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilter(new RedirectFilter(), "/p", "/person").build()
|
||||
.perform(post("/persons").param("name", "Andy"))
|
||||
.andExpect(status().isMovedTemporarily())
|
||||
.andExpect(redirectedUrl("/person/1"))
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("id"))
|
||||
.andExpect(flash().attributeCount(1))
|
||||
.andExpect(flash().attribute("message", "success!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWrapsRequestResponse() throws Exception {
|
||||
standaloneSetup(new PersonController())
|
||||
.addFilters(new WrappingRequestResponseFilter()).build()
|
||||
.perform(post("/user"))
|
||||
.andExpect(model().attribute("principal", WrappingRequestResponseFilter.PRINCIPAL_NAME));
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class PersonController {
|
||||
@RequestMapping(value="/persons", method=RequestMethod.POST)
|
||||
public String save(@Valid Person person, Errors errors, RedirectAttributes redirectAttrs) {
|
||||
if (errors.hasErrors()) {
|
||||
return "person/add";
|
||||
}
|
||||
redirectAttrs.addAttribute("id", "1");
|
||||
redirectAttrs.addFlashAttribute("message", "success!");
|
||||
return "redirect:/person/{id}";
|
||||
}
|
||||
|
||||
@RequestMapping(value="/user")
|
||||
public ModelAndView user(Principal principal) {
|
||||
return new ModelAndView("user/view", "principal", principal.getName());
|
||||
}
|
||||
|
||||
@RequestMapping(value="/forward")
|
||||
public String forward() {
|
||||
return "forward:/persons";
|
||||
}
|
||||
}
|
||||
|
||||
private class ContinueFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WrappingRequestResponseFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String PRINCIPAL_NAME = "WrapRequestResponseFilterPrincipal";
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
filterChain.doFilter(new HttpServletRequestWrapper(request) {
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return new Principal() {
|
||||
public String getName() {
|
||||
return PRINCIPAL_NAME;
|
||||
}
|
||||
};
|
||||
}
|
||||
}, new HttpServletResponseWrapper(response));
|
||||
}
|
||||
}
|
||||
|
||||
private class RedirectFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
response.sendRedirect("/login");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.*;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
/**
|
||||
* Redirect scenarios including saving and retrieving flash attributes.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RedirectTests {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = standaloneSetup(new PersonController()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void save() throws Exception {
|
||||
this.mockMvc.perform(post("/persons").param("name", "Andy"))
|
||||
.andExpect(status().isMovedTemporarily())
|
||||
.andExpect(redirectedUrl("/persons/Joe"))
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("name"))
|
||||
.andExpect(flash().attributeCount(1))
|
||||
.andExpect(flash().attribute("message", "success!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveWithErrors() throws Exception {
|
||||
this.mockMvc.perform(post("/persons"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("persons/add"))
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("person"))
|
||||
.andExpect(flash().attributeCount(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPerson() throws Exception {
|
||||
this.mockMvc.perform(get("/persons/Joe").flashAttr("message", "success!"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("persons/index"))
|
||||
.andExpect(model().size(2))
|
||||
.andExpect(model().attribute("person", new Person("Joe")))
|
||||
.andExpect(model().attribute("message", "success!"))
|
||||
.andExpect(flash().attributeCount(0));
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class PersonController {
|
||||
|
||||
@RequestMapping(value="/persons/{name}", method=RequestMethod.GET)
|
||||
public String getPerson(@PathVariable String name, Model model) {
|
||||
model.addAttribute(new Person(name));
|
||||
return "persons/index";
|
||||
}
|
||||
|
||||
@RequestMapping(value="/persons", method=RequestMethod.POST)
|
||||
public String save(@Valid Person person, Errors errors, RedirectAttributes redirectAttrs) {
|
||||
if (errors.hasErrors()) {
|
||||
return "persons/add";
|
||||
}
|
||||
redirectAttrs.addAttribute("name", "Joe");
|
||||
redirectAttrs.addFlashAttribute("message", "success!");
|
||||
return "redirect:/persons/{name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.test.web.mock.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Demonstrates how to implement and plug in a custom {@link RequestPostProcessor}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestBuilderTests {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.mockMvc = standaloneSetup(new SampleController())
|
||||
.defaultRequest(get("/").accept(MediaType.TEXT_PLAIN))
|
||||
.alwaysExpect(status().isOk()).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fooHeader() throws Exception {
|
||||
this.mockMvc.perform(get("/").with(headers().foo("a=b"))).andExpect(
|
||||
content().string("Foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void barHeader() throws Exception {
|
||||
this.mockMvc.perform(get("/").with(headers().bar("a=b"))).andExpect(
|
||||
content().string("Bar"));
|
||||
}
|
||||
|
||||
private static HeaderRequestPostProcessor headers() {
|
||||
return new HeaderRequestPostProcessor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@code RequestPostProcessor} with additional request
|
||||
* building methods.
|
||||
*/
|
||||
private static class HeaderRequestPostProcessor implements RequestPostProcessor {
|
||||
|
||||
private HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
public HeaderRequestPostProcessor foo(String value) {
|
||||
this.headers.add("Foo", value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HeaderRequestPostProcessor bar(String value) {
|
||||
this.headers.add("Bar", value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
for (String headerName : this.headers.keySet()) {
|
||||
request.addHeader(headerName, this.headers.get(headerName));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
private static class SampleController {
|
||||
|
||||
@RequestMapping(headers = "Foo")
|
||||
@ResponseBody
|
||||
public String handleFoo() {
|
||||
return "Foo";
|
||||
}
|
||||
|
||||
@RequestMapping(headers = "Bar")
|
||||
@ResponseBody
|
||||
public String handleBar() {
|
||||
return "Bar";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Tests demonstrating the use of request parameters.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class RequestParameterTests {
|
||||
|
||||
@Test
|
||||
public void queryParameter() throws Exception {
|
||||
|
||||
standaloneSetup(new PersonController()).build()
|
||||
.perform(get("/search?name=George").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.name").value("George"));
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private class PersonController {
|
||||
|
||||
@RequestMapping(value="/search")
|
||||
@ResponseBody
|
||||
public Person get(@RequestParam String name) {
|
||||
Person person = new Person(name);
|
||||
return person;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.*;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Response written from {@code @ResponseBody} method.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ResponseBodyTests {
|
||||
|
||||
@Test
|
||||
public void json() throws Exception {
|
||||
|
||||
standaloneSetup(new PersonController()).build()
|
||||
.perform(get("/person/Lee").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType("application/json;charset=UTF-8"))
|
||||
.andExpect(jsonPath("$.name").value("Lee"));
|
||||
}
|
||||
|
||||
@Controller
|
||||
private class PersonController {
|
||||
|
||||
@RequestMapping(value="/person/{name}")
|
||||
@ResponseBody
|
||||
public Person get(@PathVariable String name) {
|
||||
Person person = new Person(name);
|
||||
return person;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.samples.standalone;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasProperty;
|
||||
import static org.springframework.test.web.mock.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.model;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.mock.servlet.result.MockMvcResultMatchers.xpath;
|
||||
import static org.springframework.test.web.mock.servlet.setup.MockMvcBuilders.standaloneSetup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.test.web.mock.Person;
|
||||
import org.springframework.test.web.mock.servlet.MockMvc;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.accept.FixedContentNegotiationStrategy;
|
||||
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.json.MappingJacksonJsonView;
|
||||
import org.springframework.web.servlet.view.xml.MarshallingView;
|
||||
|
||||
/**
|
||||
* Tests with view resolution.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class ViewResolutionTests {
|
||||
|
||||
@Test
|
||||
public void testJspOnly() throws Exception {
|
||||
|
||||
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
|
||||
viewResolver.setPrefix("/WEB-INF/");
|
||||
viewResolver.setSuffix(".jsp");
|
||||
|
||||
standaloneSetup(new PersonController()).setViewResolvers(viewResolver).build()
|
||||
.perform(get("/person/Corea"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("person"))
|
||||
.andExpect(forwardedUrl("/WEB-INF/person/show.jsp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonOnly() throws Exception {
|
||||
|
||||
standaloneSetup(new PersonController()).setSingleView(new MappingJacksonJsonView()).build()
|
||||
.perform(get("/person/Corea"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.person.name").value("Corea"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlOnly() throws Exception {
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(Person.class);
|
||||
|
||||
standaloneSetup(new PersonController()).setSingleView(new MarshallingView(marshaller)).build()
|
||||
.perform(get("/person/Corea"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType(MediaType.APPLICATION_XML))
|
||||
.andExpect(xpath("/person/name/text()").string(equalTo("Corea")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContentNegotiation() throws Exception {
|
||||
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(Person.class);
|
||||
|
||||
List<View> viewList = new ArrayList<View>();
|
||||
viewList.add(new MappingJacksonJsonView());
|
||||
viewList.add(new MarshallingView(marshaller));
|
||||
|
||||
ContentNegotiationManager manager = new ContentNegotiationManager(
|
||||
new HeaderContentNegotiationStrategy(), new FixedContentNegotiationStrategy(MediaType.TEXT_HTML));
|
||||
|
||||
ContentNegotiatingViewResolver cnViewResolver = new ContentNegotiatingViewResolver();
|
||||
cnViewResolver.setDefaultViews(viewList);
|
||||
cnViewResolver.setContentNegotiationManager(manager);
|
||||
cnViewResolver.afterPropertiesSet();
|
||||
|
||||
MockMvc mockMvc =
|
||||
standaloneSetup(new PersonController())
|
||||
.setViewResolvers(cnViewResolver, new InternalResourceViewResolver())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(get("/person/Corea"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(model().size(1))
|
||||
.andExpect(model().attributeExists("person"))
|
||||
.andExpect(forwardedUrl("person/show"));
|
||||
|
||||
mockMvc.perform(get("/person/Corea").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.person.name").value("Corea"));
|
||||
|
||||
mockMvc.perform(get("/person/Corea").accept(MediaType.APPLICATION_XML))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().mimeType(MediaType.APPLICATION_XML))
|
||||
.andExpect(xpath("/person/name/text()").string(equalTo("Corea")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultViewResolver() throws Exception {
|
||||
|
||||
standaloneSetup(new PersonController()).build()
|
||||
.perform(get("/person/Corea"))
|
||||
.andExpect(model().attribute("person", hasProperty("name", equalTo("Corea"))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(forwardedUrl("person/show")); // InternalResourceViewResolver
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class PersonController {
|
||||
|
||||
@RequestMapping(value="/person/{name}", method=RequestMethod.GET)
|
||||
public String show(@PathVariable String name, Model model) {
|
||||
Person person = new Person(name);
|
||||
model.addAttribute(person);
|
||||
return "person/show";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.samples.standalone.resulthandlers;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* Print debugging information about the executed request and response to System.out.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class PrintingResultHandlerTests {
|
||||
|
||||
@Test
|
||||
public void testPrint() throws Exception {
|
||||
|
||||
// Not testing anything, uncomment to see the output
|
||||
|
||||
// standaloneSetup(new SimpleController()).build().perform(get("/")).andDo(print());
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class SimpleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String hello() {
|
||||
return "Hello world";
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user