From ed709780714fb4d5c52e491dbf804d7c388fd177 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 4 Apr 2019 16:49:46 -0400 Subject: [PATCH] verify() fails if there are failed requests Normally failed requests fail the test but they're suppressed for some reason (e.g. in async callback) then verify should still correctly report the failures. Closes gh-21799 --- .../AbstractRequestExpectationManager.java | 20 +++++++++++++-- .../web/client/MockRestServiceServer.java | 8 ++++-- .../client/MockRestServiceServerTests.java | 25 ++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) 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"); + } + } }