001/* 002 * Copyright 2002-2016 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.test.web.client; 018 019import java.io.IOException; 020import java.util.LinkedList; 021import java.util.List; 022 023import org.springframework.http.client.ClientHttpRequest; 024import org.springframework.http.client.ClientHttpResponse; 025import org.springframework.util.Assert; 026 027/** 028 * Default implementation of {@code RequestExpectation} that simply delegates 029 * to the request matchers and the response creator it contains. 030 * 031 * @author Rossen Stoyanchev 032 * @since 4.3 033 */ 034public class DefaultRequestExpectation implements RequestExpectation { 035 036 private final RequestCount requestCount; 037 038 private final List<RequestMatcher> requestMatchers = new LinkedList<RequestMatcher>(); 039 040 private ResponseCreator responseCreator; 041 042 043 /** 044 * Create a new request expectation that should be called a number of times 045 * as indicated by {@code RequestCount}. 046 * @param expectedCount the expected request expectedCount 047 */ 048 public DefaultRequestExpectation(ExpectedCount expectedCount, RequestMatcher requestMatcher) { 049 Assert.notNull(expectedCount, "ExpectedCount is required"); 050 Assert.notNull(requestMatcher, "RequestMatcher is required"); 051 this.requestCount = new RequestCount(expectedCount); 052 this.requestMatchers.add(requestMatcher); 053 } 054 055 056 protected RequestCount getRequestCount() { 057 return this.requestCount; 058 } 059 060 protected List<RequestMatcher> getRequestMatchers() { 061 return this.requestMatchers; 062 } 063 064 protected ResponseCreator getResponseCreator() { 065 return this.responseCreator; 066 } 067 068 @Override 069 public ResponseActions andExpect(RequestMatcher requestMatcher) { 070 Assert.notNull(requestMatcher, "RequestMatcher is required"); 071 this.requestMatchers.add(requestMatcher); 072 return this; 073 } 074 075 @Override 076 public void andRespond(ResponseCreator responseCreator) { 077 Assert.notNull(responseCreator, "ResponseCreator is required"); 078 this.responseCreator = responseCreator; 079 } 080 081 @Override 082 public void match(ClientHttpRequest request) throws IOException { 083 for (RequestMatcher matcher : getRequestMatchers()) { 084 matcher.match(request); 085 } 086 } 087 088 @Override 089 public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException { 090 ResponseCreator responseCreator = getResponseCreator(); 091 if (responseCreator == null) { 092 throw new IllegalStateException("createResponse called before ResponseCreator was set"); 093 } 094 getRequestCount().incrementAndValidate(); 095 return responseCreator.createResponse(request); 096 } 097 098 @Override 099 public boolean hasRemainingCount() { 100 return getRequestCount().hasRemainingCount(); 101 } 102 103 @Override 104 public boolean isSatisfied() { 105 return getRequestCount().isSatisfied(); 106 } 107 108 109 /** 110 * Helper class that keeps track of actual vs expected request count. 111 */ 112 protected static class RequestCount { 113 114 private final ExpectedCount expectedCount; 115 116 private int matchedRequestCount; 117 118 public RequestCount(ExpectedCount expectedCount) { 119 this.expectedCount = expectedCount; 120 } 121 122 public ExpectedCount getExpectedCount() { 123 return this.expectedCount; 124 } 125 126 public int getMatchedRequestCount() { 127 return this.matchedRequestCount; 128 } 129 130 public void incrementAndValidate() { 131 this.matchedRequestCount++; 132 if (getMatchedRequestCount() > getExpectedCount().getMaxCount()) { 133 throw new AssertionError("No more calls expected."); 134 } 135 } 136 137 public boolean hasRemainingCount() { 138 return (getMatchedRequestCount() < getExpectedCount().getMaxCount()); 139 } 140 141 public boolean isSatisfied() { 142 // Only validate min count since max count is checked on every request... 143 return (getMatchedRequestCount() >= getExpectedCount().getMinCount()); 144 } 145 } 146 147}