diff --git a/spring-test/src/main/java/org/springframework/test/web/client/AbstractRequestExpectationManager.java b/spring-test/src/main/java/org/springframework/test/web/client/AbstractRequestExpectationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..242ab77c597807a518ba6abfcce37f32278deea6 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/client/AbstractRequestExpectationManager.java @@ -0,0 +1,79 @@ +/* + * 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; + +/** + * Base class for {@code RequestExpectationManager} implementations. + * Creates and contains expectations and stores actual requests. + * + *

Sub-classes are responsible for matching actual to expected requests and + * for verifying remaining expectations at the end. + * + * @author Rossen Stoyanchev + * @since 4.3 + */ +public abstract class AbstractRequestExpectationManager implements RequestExpectationManager { + + private final List expectations = new LinkedList(); + + private final List requests = new LinkedList(); + + + public AbstractRequestExpectationManager() { + } + + public AbstractRequestExpectationManager(List expectations) { + this.expectations.addAll(expectations); + } + + + @Override + public List getExpectations() { + return this.expectations; + } + + @Override + public List 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); + getExpectations().add(expectation); + return expectation; + } + + @Override + public ClientHttpResponse validateRequest(ClientHttpRequest request) throws IOException { + ClientHttpResponse response = validateRequestInternal(request); + getRequests().add(request); + return response; + } + + protected abstract ClientHttpResponse validateRequestInternal(ClientHttpRequest request) + throws IOException; + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/client/DefaultResponseActions.java b/spring-test/src/main/java/org/springframework/test/web/client/DefaultResponseActions.java index 9cccf6d9250c579d49788432632eb6a514c6a24d..4b76aa1ac90428523aa858c4b36bbbee703b6653 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/DefaultResponseActions.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/DefaultResponseActions.java @@ -32,7 +32,7 @@ import org.springframework.util.Assert; * @author Rossen Stoyanchev * @since 4.3 */ -class DefaultResponseActions implements ResponseActions, RequestMatcher, ResponseCreator { +class DefaultResponseActions implements ResponseActions, RequestExpectation { private final List requestMatchers = new LinkedList(); diff --git a/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java b/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java index b2577d2ca0413643b3767a6cc76cf0bf2617d7b1..0c31c74cb430ebebfdd532c3bc8df8588d1df44f 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java @@ -18,8 +18,6 @@ package org.springframework.test.web.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; @@ -98,11 +96,7 @@ import org.springframework.web.client.support.RestGatewaySupport; */ public class MockRestServiceServer { - private final List responseActions = - new LinkedList(); - - private final List requests = - new LinkedList(); + private RequestExpectationManager expectationManager = new OrderedRequestExpectationManager(); /** @@ -123,7 +117,7 @@ public class MockRestServiceServer { public static MockRestServiceServer createServer(RestTemplate restTemplate) { Assert.notNull(restTemplate, "'restTemplate' must not be null"); MockRestServiceServer mockServer = new MockRestServiceServer(); - RequestMatcherClientHttpRequestFactory factory = mockServer.new RequestMatcherClientHttpRequestFactory(); + MockClientHttpRequestFactory factory = mockServer.new MockClientHttpRequestFactory(); restTemplate.setRequestFactory(factory); return mockServer; } @@ -137,7 +131,7 @@ public class MockRestServiceServer { public static MockRestServiceServer createServer(AsyncRestTemplate asyncRestTemplate) { Assert.notNull(asyncRestTemplate, "'asyncRestTemplate' must not be null"); MockRestServiceServer mockServer = new MockRestServiceServer(); - RequestMatcherClientHttpRequestFactory factory = mockServer.new RequestMatcherClientHttpRequestFactory(); + MockClientHttpRequestFactory factory = mockServer.new MockClientHttpRequestFactory(); asyncRestTemplate.setAsyncRequestFactory(factory); return mockServer; } @@ -154,48 +148,38 @@ public class MockRestServiceServer { } + /** + * When this option is set, the order in which requests are executed does not + * need to match the order in which expected requests are declared. + */ + public MockRestServiceServer setIgnoreRequestOrder() { + String message = "Cannot switch to unordered mode after actual requests are made."; + Assert.state(this.expectationManager.getRequests().isEmpty(), message); + List expectations = this.expectationManager.getExpectations(); + this.expectationManager = new UnorderedRequestExpectationManager(expectations); + return this; + } + /** * Set up a new HTTP request expectation. The returned {@link ResponseActions} * is used to set up further expectations and to define the response. *

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 MockRestRequestMatchers} + * @param matcher a request expectation, see {@link MockRestRequestMatchers} * @return used to set up further expectations or to define a response */ - public ResponseActions expect(RequestMatcher requestMatcher) { - Assert.state(this.requests.isEmpty(), "Can't add more expected requests with test already underway"); - DefaultResponseActions request = new DefaultResponseActions(requestMatcher); - this.responseActions.add(request); - return request; + public ResponseActions expect(RequestMatcher matcher) { + return this.expectationManager.expectRequest(matcher); } + /** * 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.responseActions.isEmpty() || this.responseActions.size() == this.requests.size()) { - return; - } - throw new AssertionError(getVerifyMessage()); - } - - private String getVerifyMessage() { - StringBuilder sb = new StringBuilder("Further request(s) expected\n"); - if (this.requests.size() > 0) { - sb.append("The following "); - } - sb.append(this.requests.size()).append(" out of "); - sb.append(this.responseActions.size()).append(" were executed"); - - if (this.requests.size() > 0) { - sb.append(":\n"); - for (MockAsyncClientHttpRequest request : this.requests) { - sb.append(request.toString()).append("\n"); - } - } - return sb.toString(); + this.expectationManager.verify(); } @@ -203,53 +187,31 @@ public class MockRestServiceServer { * Mock ClientHttpRequestFactory that creates requests by iterating * over the list of expected {@link DefaultResponseActions}'s. */ - private class RequestMatcherClientHttpRequestFactory - implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory { - - private Iterator requestIterator; + private class MockClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory { @Override - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { return createRequestInternal(uri, httpMethod); } @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException { + public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) { return createRequestInternal(uri, httpMethod); } - private MockAsyncClientHttpRequest createRequestInternal(URI uri, HttpMethod httpMethod) { + private MockAsyncClientHttpRequest createRequestInternal(URI uri, HttpMethod method) { Assert.notNull(uri, "'uri' must not be null"); - Assert.notNull(httpMethod, "'httpMethod' must not be null"); + Assert.notNull(method, "'httpMethod' must not be null"); + + return new MockAsyncClientHttpRequest(method, uri) { - MockAsyncClientHttpRequest request = new MockAsyncClientHttpRequest(httpMethod, uri) { @Override protected ClientHttpResponse executeInternal() throws IOException { - ClientHttpResponse response = validateRequest(this); + ClientHttpResponse response = expectationManager.validateRequest(this); setResponse(response); return response; } }; - - MockRestServiceServer.this.requests.add(request); - return request; - } - - private ClientHttpResponse validateRequest(MockAsyncClientHttpRequest request) - throws IOException { - - if (this.requestIterator == null) { - this.requestIterator = MockRestServiceServer.this.responseActions.iterator(); - } - if (!this.requestIterator.hasNext()) { - throw new AssertionError("No further requests expected: HTTP " + - request.getMethod() + " " + request.getURI()); - } - - DefaultResponseActions responseActions = this.requestIterator.next(); - responseActions.match(request); - - return responseActions.createResponse(request); } } diff --git a/spring-test/src/main/java/org/springframework/test/web/client/OrderedRequestExpectationManager.java b/spring-test/src/main/java/org/springframework/test/web/client/OrderedRequestExpectationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..12437e4a9aa9b497c0e7ca92cc312c4bcc15ab22 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/client/OrderedRequestExpectationManager.java @@ -0,0 +1,78 @@ +/* + * 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.net.URI; +import java.util.Iterator; + +import org.springframework.http.HttpMethod; +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. + * + * @author Rossen Stoyanchev + * @since 4.3 + */ +public class OrderedRequestExpectationManager extends AbstractRequestExpectationManager { + + private Iterator iterator; + + + @Override + public ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException { + if (this.iterator == null) { + this.iterator = getExpectations().iterator(); + } + if (!this.iterator.hasNext()) { + HttpMethod method = request.getMethod(); + URI uri = request.getURI(); + throw new AssertionError("No further requests expected: HTTP " + method + " " + uri); + } + RequestExpectation expectation = this.iterator.next(); + expectation.match(request); + return expectation.createResponse(request); + } + + @Override + public void verify() { + if (getExpectations().isEmpty() || getExpectations().size() == getRequests().size()) { + return; + } + throw new AssertionError(getVerifyMessage()); + } + + private String getVerifyMessage() { + StringBuilder sb = new StringBuilder("Further request(s) expected\n"); + if (getRequests().size() > 0) { + sb.append("The following "); + } + sb.append(getRequests().size()).append(" out of "); + sb.append(getExpectations().size()).append(" were executed"); + + if (getRequests().size() > 0) { + sb.append(":\n"); + for (ClientHttpRequest request : getRequests()) { + sb.append(request.toString()).append("\n"); + } + } + return sb.toString(); + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectation.java b/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectation.java new file mode 100644 index 0000000000000000000000000000000000000000..cec8c3744b9e8bd7d39100070eb2669dbb10708a --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectation.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * A contract that combines {@code RequestMatcher} with {@code ResponseCreator} + * to define an expected request and a response to use for it. + * + * @author Rossen Stoyanchev + * @since 4.3 + */ +public interface RequestExpectation extends RequestMatcher, ResponseCreator { + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectationManager.java b/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e919a20e029be8d0a277e4b46016b80960c6e80d --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/client/RequestExpectationManager.java @@ -0,0 +1,68 @@ +/* + * 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.List; + +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpResponse; + +/** + * Contract to manage creating HTTP request expectations, apply them to actual + * requests (in strict or random order), and at the end verify whether all + * expectations were met. + * + * @author Rossen Stoyanchev + * @since 4.3 + */ +public interface RequestExpectationManager { + + /** + * Return the list of declared request expectations. + */ + List getExpectations(); + + /** + * Return the list of actual requests. + */ + List getRequests(); + + /** + * Set up a new request expectation. The returned {@link ResponseActions} is + * used to add more expectations and define a response. + * @param requestMatcher a request expectation + * @return for setting up further expectations and define a response + */ + ResponseActions expectRequest(RequestMatcher requestMatcher); + + /** + * Validate the given actual request against the declared expectations + * raising {@link AssertionError} if not met. + * @param request the request + * @return the response to return if the request was validated. + * @throws AssertionError when some expectations were not met + * @throws IOException + */ + ClientHttpResponse validateRequest(ClientHttpRequest request) throws IOException; + + /** + * Verify that all expectations have been met. + * @throws AssertionError when some expectations were not met + */ + void verify(); + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/client/UnorderedRequestExpectationManager.java b/spring-test/src/main/java/org/springframework/test/web/client/UnorderedRequestExpectationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..2e658d607768c5cce200fa900fd0bb3635922dfb --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/web/client/UnorderedRequestExpectationManager.java @@ -0,0 +1,93 @@ +/* + * 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.net.URI; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.http.HttpMethod; +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. + * + * @author Rossen Stoyanchev + * @since 4.3 + */ +public class UnorderedRequestExpectationManager extends AbstractRequestExpectationManager { + + private final List remainingExpectations = new LinkedList(); + + + public UnorderedRequestExpectationManager() { + } + + public UnorderedRequestExpectationManager(List expectations) { + super(expectations); + } + + + @Override + public ClientHttpResponse validateRequestInternal(ClientHttpRequest request) throws IOException { + if (getRequests().isEmpty()) { + this.remainingExpectations.addAll(getExpectations()); + } + for (RequestExpectation expectation : getExpectations()) { + try { + expectation.match(request); + this.remainingExpectations.remove(expectation); + return expectation.createResponse(request); + } + catch (AssertionError error) { + // Ignore + } + } + HttpMethod method = request.getMethod(); + URI uri = request.getURI(); + throw new AssertionError("Unexpected request: HTTP " + method + " " + uri); + } + + @Override + public void verify() { + if (getExpectations().isEmpty() || this.remainingExpectations.isEmpty()) { + return; + } + throw new AssertionError(getVerifyMessage()); + } + + private String getVerifyMessage() { + StringBuilder sb = new StringBuilder("Further request(s) expected\n"); + if (getRequests().size() > 0) { + sb.append("The following "); + } + sb.append(getRequests().size()).append(" were executed"); + sb.append(" leaving ").append(this.remainingExpectations.size()).append(" expectations."); + + if (getRequests().size() > 0) { + sb.append(":\n"); + for (ClientHttpRequest request : getRequests()) { + sb.append(request.toString()).append("\n"); + } + } + return sb.toString(); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java b/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java deleted file mode 100644 index c5ae4fe36412055daa544963909ca2b675492a0c..0000000000000000000000000000000000000000 --- a/spring-test/src/test/java/org/springframework/test/web/client/MockClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2014 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.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.web.client.RestTemplate; - -import static org.junit.Assert.*; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; - -/** - * Tests for - * {@link org.springframework.test.web.client.MockMvcClientHttpRequestFactory}. - * - * @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 actual = this.factory.createRequest(uri, HttpMethod.GET); - - 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: HTTP GET /foo", 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")); - } - } - -} diff --git a/spring-test/src/test/java/org/springframework/test/web/client/OrderedRequestExpectationManagerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/OrderedRequestExpectationManagerTests.java new file mode 100644 index 0000000000000000000000000000000000000000..1a578d3888e3d9b3f645ffba6fc4b16e221e793d --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/client/OrderedRequestExpectationManagerTests.java @@ -0,0 +1,90 @@ +/* + * 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.net.URI; +import java.net.URISyntaxException; + +import org.junit.Test; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockAsyncClientHttpRequest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.anything; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +/** + * Unit tests for {@link AbstractRequestExpectationManager}. + * @author Rossen Stoyanchev + */ +public class OrderedRequestExpectationManagerTests { + + private OrderedRequestExpectationManager manager = new OrderedRequestExpectationManager(); + + + @Test + public void validateWithUnexpectedRequest() throws Exception { + try { + this.manager.validateRequest(request(HttpMethod.GET, "/foo")); + } + catch (AssertionError error) { + assertEquals("No further requests expected: HTTP GET /foo", error.getMessage()); + } + } + + @Test + public void verify() throws Exception { + this.manager.expectRequest(anything()).andRespond(withSuccess()); + this.manager.expectRequest(anything()).andRespond(withSuccess()); + + this.manager.validateRequest(request(HttpMethod.GET, "/foo")); + this.manager.validateRequest(request(HttpMethod.POST, "/bar")); + this.manager.verify(); + } + + @Test + public void verifyWithZeroExpectations() throws Exception { + this.manager.verify(); + } + + @Test + public void verifyWithRemainingExpectations() throws Exception { + this.manager.expectRequest(anything()).andRespond(withSuccess()); + this.manager.expectRequest(anything()).andRespond(withSuccess()); + + this.manager.validateRequest(request(HttpMethod.GET, "/foo")); + try { + this.manager.verify(); + } + catch (AssertionError error) { + assertTrue(error.getMessage(), error.getMessage().contains("1 out of 2 were executed")); + } + } + + private ClientHttpRequest request(HttpMethod method, String url) { + try { + return new MockAsyncClientHttpRequest(method, new URI(url)); + } + catch (URISyntaxException ex) { + throw new IllegalStateException(ex); + } + } + +}