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 index ac373f89fb..a70b948860 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -20,10 +20,13 @@ import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; @@ -49,6 +52,8 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect private final List requests = new LinkedList<>(); + private final Map requestFailures = new LinkedHashMap<>(); + /** * Return a read-only list of the expectations. @@ -91,6 +96,10 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect expectation = matchRequest(request); } } + catch (Throwable ex) { + this.requestFailures.put(request, ex); + throw ex; + } finally { this.requests.add(request); } @@ -129,7 +138,8 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect * @since 5.0.3 */ protected RequestExpectation matchRequest(ClientHttpRequest request) throws IOException { - throw new UnsupportedOperationException("It looks like neither the deprecated \"validateRequestInternal\"" + + throw new UnsupportedOperationException( + "It looks like neither the deprecated \"validateRequestInternal\"" + "nor its replacement (this method) are implemented."); } @@ -148,6 +158,12 @@ public abstract class AbstractRequestExpectationManager implements RequestExpect String message = "Further request(s) expected leaving " + count + " unsatisfied expectation(s).\n"; throw new AssertionError(message + getRequestDetails()); } + if (!this.requestFailures.isEmpty()) { + throw new AssertionError("Some requests did not execute successfully.\n" + + this.requestFailures.entrySet().stream() + .map(entry -> "Failed request:\n" + entry.getKey() + "\n" + entry.getValue()) + .collect(Collectors.joining("\n", "\n", ""))); + } } /** 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 5666e92b41..a16bdc4ef3 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 @@ -305,11 +305,15 @@ public final class MockRestServiceServer { } @Override - public org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) { + public org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest( + URI uri, HttpMethod httpMethod) { + return createRequestInternal(uri, httpMethod); } - private org.springframework.mock.http.client.MockAsyncClientHttpRequest createRequestInternal(URI uri, HttpMethod method) { + private org.springframework.mock.http.client.MockAsyncClientHttpRequest createRequestInternal( + URI uri, HttpMethod method) { + Assert.notNull(uri, "'uri' must not be null"); Assert.notNull(method, "'httpMethod' must not be null"); diff --git a/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java index 45462658d5..f9af4dd58c 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/MockRestServiceServerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -23,7 +23,9 @@ import org.junit.Test; import org.springframework.test.web.client.MockRestServiceServer.MockRestServiceServerBuilder; import org.springframework.web.client.RestTemplate; +import static org.assertj.core.api.Assertions.*; 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.*; @@ -132,4 +134,25 @@ public class MockRestServiceServerTests { server.verify(); } + @Test // gh-21799 + public void verifyShouldFailIfRequestsFailed() { + MockRestServiceServer server = MockRestServiceServer.bindTo(this.restTemplate).build(); + server.expect(once(), requestTo("/remoteurl")).andRespond(withSuccess()); + + this.restTemplate.postForEntity("/remoteurl", null, String.class); + try { + this.restTemplate.postForEntity("/remoteurl", null, String.class); + } + catch (AssertionError error) { + assertThat(error.getMessage()).startsWith("No further requests expected"); + } + + try { + server.verify(); + fail("Expected verify failure"); + } + catch (AssertionError error) { + assertThat(error.getMessage()).startsWith("Some requests did not execute successfully"); + } + } }