This commit is contained in:
Rossen Stoyanchev 2017-07-25 12:27:33 +02:00
parent 29c112c010
commit d20e5fcc59
6 changed files with 75 additions and 54 deletions

View File

@ -19,6 +19,7 @@ package org.springframework.test.web.client;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@ -49,26 +50,32 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
private final List<ClientHttpRequest> requests = new LinkedList<>();
/**
* Return a read-only list of the expectations.
*/
protected List<RequestExpectation> getExpectations() {
return this.expectations;
return Collections.unmodifiableList(this.expectations);
}
/**
* Return a read-only list of requests executed so far.
*/
protected List<ClientHttpRequest> getRequests() {
return this.requests;
return Collections.unmodifiableList(this.requests);
}
@Override
public ResponseActions expectRequest(ExpectedCount count, RequestMatcher matcher) {
Assert.state(getRequests().isEmpty(), "Cannot add more expectations after actual requests are made");
Assert.state(this.requests.isEmpty(), "Cannot add more expectations after actual requests are made");
RequestExpectation expectation = new DefaultRequestExpectation(count, matcher);
getExpectations().add(expectation);
this.expectations.add(expectation);
return expectation;
}
@Override
public ClientHttpResponse validateRequest(ClientHttpRequest request) throws IOException {
List<ClientHttpRequest> requests = getRequests();
List<ClientHttpRequest> requests = this.requests;
synchronized (requests) {
if (requests.isEmpty()) {
afterExpectationsDeclared();
@ -80,25 +87,26 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
}
/**
* Invoked after the phase of declaring expected requests is over. This is
* detected from {@link #validateRequest} on the first actual request.
* Invoked at the time of the first actual request, which effectively means
* the expectations declaration phase is over.
*/
protected void afterExpectationsDeclared() {
}
/**
* Subclasses must implement the actual validation of the request
* matching it to a declared expectation.
* Sub-classes must implement the actual validation of the request
* matching to declared expectations.
*/
protected abstract ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException;
protected abstract ClientHttpResponse validateRequestInternal(ClientHttpRequest request)
throws IOException;
@Override
public void verify() {
if (getExpectations().isEmpty()) {
if (this.expectations.isEmpty()) {
return;
}
int count = 0;
for (RequestExpectation expectation : getExpectations()) {
for (RequestExpectation expectation : this.expectations) {
if (!expectation.isSatisfied()) {
count++;
}
@ -114,10 +122,10 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
*/
protected String getRequestDetails() {
StringBuilder sb = new StringBuilder();
sb.append(getRequests().size()).append(" request(s) executed");
if (!getRequests().isEmpty()) {
sb.append(this.requests.size()).append(" request(s) executed");
if (!this.requests.isEmpty()) {
sb.append(":\n");
for (ClientHttpRequest request : getRequests()) {
for (ClientHttpRequest request : this.requests) {
sb.append(request.toString()).append("\n");
}
}
@ -146,9 +154,7 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
/**
* Helper class to manage a group of request expectations. It helps with
* operations against the entire group such as finding a match and updating
* (add or remove) based on expected request count.
* Helper class to manage a group of remaining expectations.
*/
protected static class RequestExpectationGroup {
@ -158,24 +164,10 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
return this.expectations;
}
public void update(RequestExpectation expectation) {
if (expectation.hasRemainingCount()) {
getExpectations().add(expectation);
}
else {
getExpectations().remove(expectation);
}
}
public void updateAll(Collection<RequestExpectation> expectations) {
for (RequestExpectation expectation : expectations) {
update(expectation);
}
}
@Nullable
public RequestExpectation findExpectation(ClientHttpRequest request) throws IOException {
for (RequestExpectation expectation : getExpectations()) {
for (RequestExpectation expectation : this.expectations) {
try {
expectation.match(request);
return expectation;
@ -187,8 +179,30 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect
return null;
}
/**
* Invoke this for an expectation that has been matched.
* <p>The given expectation will either be stored if it has a remaining
* count or it will be removed otherwise.
*/
public void update(RequestExpectation expectation) {
if (expectation.hasRemainingCount()) {
this.expectations.add(expectation);
}
else {
this.expectations.remove(expectation);
}
}
/**
* Collection variant of {@link #update(RequestExpectation)} that can
* be used to insert expectations.
*/
public void updateAll(Collection<RequestExpectation> expectations) {
expectations.forEach(this::update);
}
public void reset() {
getExpectations().clear();
this.expectations.clear();
}
}

View File

@ -273,7 +273,8 @@ public class MockRestServiceServer {
* Mock ClientHttpRequestFactory that creates requests by iterating
* over the list of expected {@link DefaultRequestExpectation}'s.
*/
private class MockClientHttpRequestFactory implements ClientHttpRequestFactory, org.springframework.http.client.AsyncClientHttpRequestFactory {
private class MockClientHttpRequestFactory implements ClientHttpRequestFactory,
org.springframework.http.client.AsyncClientHttpRequestFactory {
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {

View File

@ -41,12 +41,12 @@ public class UnorderedRequestExpectationManager extends AbstractRequestExpectati
@Override
public ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException {
RequestExpectation expectation = this.remainingExpectations.findExpectation(request);
if (expectation != null) {
ClientHttpResponse response = expectation.createResponse(request);
this.remainingExpectations.update(expectation);
return response;
if (expectation == null) {
throw createUnexpectedRequestError(request);
}
throw createUnexpectedRequestError(request);
ClientHttpResponse response = expectation.createResponse(request);
this.remainingExpectations.update(expectation);
return response;
}
@Override

View File

@ -28,14 +28,16 @@ import org.springframework.http.client.ClientHttpRequest;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpMethod.*;
import static org.springframework.test.web.client.ExpectedCount.*;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.test.web.client.ExpectedCount.once;
import static org.springframework.test.web.client.ExpectedCount.twice;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
/**
* Unit tests for {@link DefaultRequestExpectation}.
*
* @author Rossen Stoyanchev
*/
public class DefaultRequestExpectationTests {

View File

@ -21,12 +21,11 @@ import org.junit.Test;
import org.springframework.test.web.client.MockRestServiceServer.MockRestServiceServerBuilder;
import org.springframework.web.client.RestTemplate;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
/**
* Unit tests for {@link MockRestServiceServer}.
*
* @author Rossen Stoyanchev
*/
public class MockRestServiceServerTests {

View File

@ -27,15 +27,20 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import static org.junit.Assert.*;
import static org.springframework.http.HttpMethod.*;
import static org.springframework.test.web.client.ExpectedCount.*;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
import static org.junit.Assert.assertEquals;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.test.web.client.ExpectedCount.max;
import static org.springframework.test.web.client.ExpectedCount.min;
import static org.springframework.test.web.client.ExpectedCount.once;
import static org.springframework.test.web.client.ExpectedCount.times;
import static org.springframework.test.web.client.ExpectedCount.twice;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
/**
* Unit tests for {@link SimpleRequestExpectationManager}.
*
* @author Rossen Stoyanchev
*/
public class SimpleRequestExpectationManagerTests {