提交 08a08725 编写于 作者: R Rossen Stoyanchev

Allow plugging in custom RequestExpectationManager

The MockRestServiceServer builder now has an option to plug in a
custom RequestExpectationManager.

Issue: SPR-11365
上级 a56c69c9
......@@ -24,11 +24,11 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* Base class for {@code RequestExpectationManager} implementations.
* Creates and contains expectations and stores actual requests.
* Base class for {@code RequestExpectationManager} implementations responsible
* for storing expectations and requests.
*
* <p>Sub-classes are responsible for matching actual to expected requests and
* for verifying remaining expectations at the end.
* <p>Sub-classes are responsible for matching requests to expectations and
* verifying there are no remaining expectations at the end.
*
* @author Rossen Stoyanchev
* @since 4.3
......@@ -40,30 +40,26 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
private final List<ClientHttpRequest> requests = new LinkedList<ClientHttpRequest>();
public AbstractRequestExpectationManager() {
}
public AbstractRequestExpectationManager(List<RequestExpectation> expectations) {
this.expectations.addAll(expectations);
}
public List<RequestExpectation> getExpectations() {
protected List<RequestExpectation> getExpectations() {
return this.expectations;
}
public List<ClientHttpRequest> getRequests() {
protected List<ClientHttpRequest> getRequests() {
return this.requests;
}
@Override
public ResponseActions expectRequest(RequestMatcher requestMatcher) {
Assert.state(getRequests().isEmpty(), "Cannot add more expectations after actual requests are made.");
DefaultResponseActions expectation = new DefaultResponseActions(requestMatcher);
RequestExpectation expectation = createExpectation(requestMatcher);
getExpectations().add(expectation);
return expectation;
}
protected RequestExpectation createExpectation(RequestMatcher requestMatcher) {
return new DefaultRequestExpectation(requestMatcher);
}
@Override
public ClientHttpResponse validateRequest(ClientHttpRequest request) throws IOException {
ClientHttpResponse response = validateRequestInternal(request);
......
......@@ -25,21 +25,20 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* Default implementation of {@code ResponseActions} that is also a composite
* {@code RequestMatcher}, invoking all request matchers it contains, as well as
* a {@code ResponseCreator} delegating to the response creator it contains.
* Default implementation of {@code RequestExpectation} that simply delegates
* to the request matchers and the response creator it contains.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
class DefaultResponseActions implements ResponseActions, RequestExpectation {
public class DefaultRequestExpectation implements RequestExpectation {
private final List<RequestMatcher> requestMatchers = new LinkedList<RequestMatcher>();
private ResponseCreator responseCreator;
public DefaultResponseActions(RequestMatcher requestMatcher) {
public DefaultRequestExpectation(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "RequestMatcher is required");
this.requestMatchers.add(requestMatcher);
}
......
......@@ -200,10 +200,19 @@ public class MockRestServiceServer {
public interface MockRestServiceServerBuilder {
/**
* When this option is set, requests can be executed in any order, i.e.
* not matching the order in which expected requests are declared.
* Allow expected requests to be executed in any order not necessarily
* matching the order of declaration. This is a shortcut for:<br>
* {@code builder.expectationManager(new UnorderedRequestExpectationManager)}
*/
MockRestServiceServerBuilder ignoreExpectOrder();
MockRestServiceServerBuilder unordered();
/**
* Configure a custom {@code RequestExpectationManager}.
* <p>By default {@link SimpleRequestExpectationManager} is used. It is
* also possible to switch to {@link UnorderedRequestExpectationManager}
* by setting {@link #unordered()}.
*/
MockRestServiceServerBuilder expectationManager(RequestExpectationManager manager);
/**
* Build the {@code MockRestServiceServer} and setting up the underlying
......@@ -220,7 +229,7 @@ public class MockRestServiceServer {
private final AsyncRestTemplate asyncRestTemplate;
private boolean ignoreExpectOrder;
private RequestExpectationManager expectationManager = new SimpleRequestExpectationManager();
public DefaultBuilder(RestTemplate restTemplate) {
......@@ -237,19 +246,21 @@ public class MockRestServiceServer {
@Override
public MockRestServiceServerBuilder ignoreExpectOrder() {
this.ignoreExpectOrder = true;
public MockRestServiceServerBuilder unordered() {
expectationManager(new UnorderedRequestExpectationManager());
return this;
}
@Override
public MockRestServiceServerBuilder expectationManager(RequestExpectationManager manager) {
Assert.notNull(manager, "'manager' is required.");
this.expectationManager = manager;
return this;
}
@Override
public MockRestServiceServer build() {
MockRestServiceServer server = (this.ignoreExpectOrder ?
new MockRestServiceServer(new UnorderedRequestExpectationManager()) :
new MockRestServiceServer());
MockRestServiceServer server = new MockRestServiceServer(this.expectationManager);
MockClientHttpRequestFactory factory = server.new MockClientHttpRequestFactory();
if (this.restTemplate != null) {
this.restTemplate.setRequestFactory(factory);
......@@ -257,7 +268,6 @@ public class MockRestServiceServer {
if (this.asyncRestTemplate != null) {
this.asyncRestTemplate.setAsyncRequestFactory(factory);
}
return server;
}
}
......@@ -265,7 +275,7 @@ public class MockRestServiceServer {
/**
* Mock ClientHttpRequestFactory that creates requests by iterating
* over the list of expected {@link DefaultResponseActions}'s.
* over the list of expected {@link DefaultRequestExpectation}'s.
*/
private class MockClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
......
......@@ -16,12 +16,16 @@
package org.springframework.test.web.client;
/**
* A contract that combines {@code RequestMatcher} with {@code ResponseCreator}
* to define an expected request and a response to use for it.
* An extension of {@code ResponseActions} that also implements
* {@code RequestMatcher} and {@code ResponseCreator}
*
* <p>{@code ResponseActions} is the API for defining expectations while
* {@code RequestExpectation} is the internal SPI to match those expectations
* to actual requests and to create responses.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
public interface RequestExpectation extends RequestMatcher, ResponseCreator {
public interface RequestExpectation extends ResponseActions, RequestMatcher, ResponseCreator {
}
......@@ -24,8 +24,8 @@ import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
/**
* {@code RequestExpectationManager} that expects requests to follow the order
* in which expected requests were declared.
* Simple {@code RequestExpectationManager} that matches requests to expectations
* sequentially, i.e. in the order of declaration of expectations.
*
* @author Rossen Stoyanchev
* @since 4.3
......@@ -43,7 +43,8 @@ public class SimpleRequestExpectationManager extends AbstractRequestExpectationM
if (!this.iterator.hasNext()) {
HttpMethod method = request.getMethod();
URI uri = request.getURI();
throw new AssertionError("No further requests expected: HTTP " + method + " " + uri);
String firstLine = "No further requests expected: HTTP " + method + " " + uri + "\n";
throw new AssertionError(createErrorMessage(firstLine));
}
RequestExpectation expectation = this.iterator.next();
expectation.match(request);
......@@ -55,11 +56,11 @@ public class SimpleRequestExpectationManager extends AbstractRequestExpectationM
if (getExpectations().isEmpty() || getExpectations().size() == getRequests().size()) {
return;
}
throw new AssertionError(getVerifyMessage());
throw new AssertionError(createErrorMessage("Further request(s) expected\n"));
}
private String getVerifyMessage() {
StringBuilder sb = new StringBuilder("Further request(s) expected\n");
private String createErrorMessage(String firstLine) {
StringBuilder sb = new StringBuilder(firstLine);
if (getRequests().size() > 0) {
sb.append("The following ");
}
......
......@@ -25,9 +25,8 @@ import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
/**
* {@code RequestExpectationManager} that tries to match actual requests to
* expected requests regardless of the order in which expected requests were
* declared.
* {@code RequestExpectationManager} that matches requests to expectations
* regardless of the order of declaration of expectations.
*
* @author Rossen Stoyanchev
* @since 4.3
......@@ -37,23 +36,20 @@ public class UnorderedRequestExpectationManager extends AbstractRequestExpectati
private final List<RequestExpectation> remainingExpectations = new LinkedList<RequestExpectation>();
public UnorderedRequestExpectationManager() {
}
public UnorderedRequestExpectationManager(List<RequestExpectation> expectations) {
super(expectations);
protected List<RequestExpectation> getRemainingExpectations() {
return this.remainingExpectations;
}
@Override
public ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException {
if (getRequests().isEmpty()) {
this.remainingExpectations.addAll(getExpectations());
getRemainingExpectations().addAll(getExpectations());
}
for (RequestExpectation expectation : getExpectations()) {
try {
expectation.match(request);
this.remainingExpectations.remove(expectation);
getRemainingExpectations().remove(expectation);
return expectation.createResponse(request);
}
catch (AssertionError error) {
......
......@@ -34,7 +34,7 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
* Unit tests for {@link AbstractRequestExpectationManager}.
* @author Rossen Stoyanchev
*/
public class OrderedRequestExpectationManagerTests {
public class SimpleRequestExpectationManagerTests {
private SimpleRequestExpectationManager manager = new SimpleRequestExpectationManager();
......@@ -45,7 +45,8 @@ public class OrderedRequestExpectationManagerTests {
this.manager.validateRequest(request(HttpMethod.GET, "/foo"));
}
catch (AssertionError error) {
assertEquals("No further requests expected: HTTP GET /foo", error.getMessage());
assertEquals("No further requests expected: HTTP GET /foo\n" +
"0 out of 0 were executed", error.getMessage());
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册