/*
* Copyright 2002-2016 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.client;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* Default implementation of {@code RequestExpectation} that simply delegates
* to the request matchers and the response creator it contains.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
public class DefaultRequestExpectation implements RequestExpectation {
private final RequestCount requestCount;
private final List<RequestMatcher> requestMatchers = new LinkedList<>();
private ResponseCreator responseCreator;
/**
* Create a new request expectation that should be called a number of times
* as indicated by {@code RequestCount}.
* @param expectedCount the expected request expectedCount
*/
public DefaultRequestExpectation(ExpectedCount expectedCount, RequestMatcher requestMatcher) {
Assert.notNull(expectedCount, "ExpectedCount is required");
Assert.notNull(requestMatcher, "RequestMatcher is required");
this.requestCount = new RequestCount(expectedCount);
this.requestMatchers.add(requestMatcher);
}
protected RequestCount getRequestCount() {
return this.requestCount;
}
protected List<RequestMatcher> getRequestMatchers() {
return this.requestMatchers;
}
protected ResponseCreator getResponseCreator() {
return this.responseCreator;
}
@Override
public ResponseActions andExpect(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "RequestMatcher is required");
this.requestMatchers.add(requestMatcher);
return this;
}
@Override
public void andRespond(ResponseCreator responseCreator) {
Assert.notNull(responseCreator, "ResponseCreator is required");
this.responseCreator = responseCreator;
}
@Override
public void match(ClientHttpRequest request) throws IOException {
for (RequestMatcher matcher : getRequestMatchers()) {
matcher.match(request);
}
}
@Override
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
ResponseCreator responseCreator = getResponseCreator();
Assert.state(responseCreator != null, "createResponse() called before ResponseCreator was set");
getRequestCount().incrementAndValidate();
return responseCreator.createResponse(request);
}
@Override
public boolean hasRemainingCount() {
return getRequestCount().hasRemainingCount();
}
@Override
public boolean isSatisfied() {
return getRequestCount().isSatisfied();
}
/**
* Helper class that keeps track of actual vs expected request count.
*/
protected static class RequestCount {
private final ExpectedCount expectedCount;
private int matchedRequestCount;
public RequestCount(ExpectedCount expectedCount) {
this.expectedCount = expectedCount;
}
public ExpectedCount getExpectedCount() {
return this.expectedCount;
}
public int getMatchedRequestCount() {
return this.matchedRequestCount;
}
public void incrementAndValidate() {
this.matchedRequestCount++;
if (getMatchedRequestCount() > getExpectedCount().getMaxCount()) {
throw new AssertionError("No more calls expected.");
}
}
public boolean hasRemainingCount() {
return (getMatchedRequestCount() < getExpectedCount().getMaxCount());
}
public boolean isSatisfied() {
// Only validate min count since max count is checked on every request...
return (getMatchedRequestCount() >= getExpectedCount().getMinCount());
}
}
}