From cd078eaad83e2c6cb441719086b460e665c20f35 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 22 Aug 2021 19:03:32 +0200 Subject: [PATCH] Use ExceptionCollector for soft assertions in MockMvc See gh-26917 --- .../test/web/servlet/ResultMatcher.java | 18 ++---- .../test/web/servlet/ResultMatcherTests.java | 62 +++++++++++++++---- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java index 1362410298..ac40b9d716 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java @@ -16,6 +16,8 @@ package org.springframework.test.web.servlet; +import org.springframework.test.util.ExceptionCollector; + /** * A {@code ResultMatcher} matches the result of an executed request against * some expectation. @@ -81,21 +83,11 @@ public interface ResultMatcher { */ static ResultMatcher matchAllSoftly(ResultMatcher... matchers) { return result -> { - String message = ""; + ExceptionCollector exceptionCollector = new ExceptionCollector(); for (ResultMatcher matcher : matchers) { - try { - matcher.match(result); - } - catch (Error | Exception ex) { - if (!message.isEmpty()) { - message += System.lineSeparator(); - } - message += ex.getMessage(); - } - } - if (!message.isEmpty()) { - throw new AssertionError(message); + exceptionCollector.execute(() -> matcher.match(result)); } + exceptionCollector.assertEmpty(); }; } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/ResultMatcherTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/ResultMatcherTests.java index 17ff058826..dd7cd3527c 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/ResultMatcherTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/ResultMatcherTests.java @@ -16,9 +16,9 @@ package org.springframework.test.web.servlet; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatNoException; @@ -31,6 +31,8 @@ import static org.assertj.core.api.Assertions.assertThatNoException; */ class ResultMatcherTests { + private static final String EOL = "\n"; + private final StubMvcResult stubMvcResult = new StubMvcResult(null, null, null, null, null, null, null); @@ -42,36 +44,74 @@ class ResultMatcherTests { } @Test - void softAssertionsWithOneFailure() { - String failureMessage = "failure message"; - ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(failingMatcher(failureMessage)); + void softAssertionsWithOneAssertionError() { + String failureMessage = "error"; + ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(assertionErrorMatcher(failureMessage)); assertThatExceptionOfType(AssertionError.class) .isThrownBy(() -> resultMatcher.match(stubMvcResult)) - .withMessage(failureMessage); + .withMessage(failureMessage) + .withNoCause() + .satisfies(error -> assertThat(error).hasNoSuppressedExceptions()); + } + + @Test + void softAssertionsWithOneRuntimeException() { + String failureMessage = "exception"; + ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(uncheckedExceptionMatcher(failureMessage)); + + assertThatExceptionOfType(RuntimeException.class) + .isThrownBy(() -> resultMatcher.match(stubMvcResult)) + .withMessage(failureMessage) + .withNoCause() + .satisfies(error -> assertThat(error).hasNoSuppressedExceptions()); + } + + @Test + void softAssertionsWithOneCheckedException() { + String failureMessage = "exception"; + ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(checkedExceptionMatcher(failureMessage)); + + assertThatExceptionOfType(Exception.class) + .isThrownBy(() -> resultMatcher.match(stubMvcResult)) + .withMessage(failureMessage) + .withNoCause() + .satisfies(exception -> assertThat(exception).hasNoSuppressedExceptions()); } @Test void softAssertionsWithTwoFailures() { String firstFailure = "firstFailure"; String secondFailure = "secondFailure"; - ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(failingMatcher(firstFailure), exceptionalMatcher(secondFailure)); + String thirdFailure = "thirdFailure"; + ResultMatcher resultMatcher = ResultMatcher.matchAllSoftly(assertionErrorMatcher(firstFailure), + checkedExceptionMatcher(secondFailure), uncheckedExceptionMatcher(thirdFailure)); assertThatExceptionOfType(AssertionError.class) .isThrownBy(() -> resultMatcher.match(stubMvcResult)) - .withMessage(firstFailure + System.lineSeparator() + secondFailure); + .withMessage("Multiple Exceptions (3):" + EOL + firstFailure + EOL + secondFailure + EOL + thirdFailure) + .satisfies(error -> assertThat(error.getSuppressed()).hasSize(3)); } - private ResultMatcher failingMatcher(String failureMessage) { - return result -> Assertions.fail(failureMessage); + private ResultMatcher assertionErrorMatcher(String failureMessage) { + return result -> { + throw new AssertionError(failureMessage); + }; } - private ResultMatcher exceptionalMatcher(String failureMessage) { + private ResultMatcher uncheckedExceptionMatcher(String failureMessage) { return result -> { throw new RuntimeException(failureMessage); }; } - void doNothing(MvcResult mvcResult) {} + private ResultMatcher checkedExceptionMatcher(String failureMessage) { + return result -> { + throw new Exception(failureMessage); + }; + } + + void doNothing(MvcResult mvcResult) { + } }