From 75179d56764ad3ae8fffcbd89e6dc2b1af5c3a45 Mon Sep 17 00:00:00 2001 From: Victor Borovlev Date: Tue, 14 Sep 2021 19:42:05 +0700 Subject: [PATCH] fix #679: Add on fail message builder for response specification --- .../itest/java/ErrorMessageITest.java | 22 +++++++++++++++++++ .../internal/ResponseSpecificationImpl.groovy | 12 +++++++++- .../specification/ResponseSpecification.java | 12 ++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/examples/rest-assured-itest-java/src/test/java/io/restassured/itest/java/ErrorMessageITest.java b/examples/rest-assured-itest-java/src/test/java/io/restassured/itest/java/ErrorMessageITest.java index b862478d5..7fa73e3cd 100644 --- a/examples/rest-assured-itest-java/src/test/java/io/restassured/itest/java/ErrorMessageITest.java +++ b/examples/rest-assured-itest-java/src/test/java/io/restassured/itest/java/ErrorMessageITest.java @@ -92,6 +92,28 @@ public class ErrorMessageITest extends WithJetty { get("/lotto"); } + @Test public void + error_message_look_ok_with_on_fail_message() { + exception.expect(AssertionError.class); + exception.expectMessage("2 expectations failed.\n" + + "JSON path lotto.lottoId doesn't match.\n" + + "Expected: a value less than <2>\n" + + " Actual: <5>\n" + + "\n" + + "JSON path lotto.winning-numbers doesn't match.\n" + + "Expected: a collection containing <21>\n" + + " Actual: <[2, 45, 34, 23, 7, 5, 3]>\n" + + "\n" + + "On fail message: An additional information to find the cause of the error"); + + expect(). + body("lotto.lottoId", lessThan(2)). + body("lotto.winning-numbers", hasItem(21)). + onFailMessage("An additional information to find the cause of the error"). + when(). + get("/lotto"); + } + @Test public void error_message_with_failed_xpath_expected_looks_ok() { exception.expect(AssertionError.class); diff --git a/rest-assured/src/main/groovy/io/restassured/internal/ResponseSpecificationImpl.groovy b/rest-assured/src/main/groovy/io/restassured/internal/ResponseSpecificationImpl.groovy index 220fb6d2b..554263c96 100644 --- a/rest-assured/src/main/groovy/io/restassured/internal/ResponseSpecificationImpl.groovy +++ b/rest-assured/src/main/groovy/io/restassured/internal/ResponseSpecificationImpl.groovy @@ -61,6 +61,7 @@ class ResponseSpecificationImpl implements FilterableResponseSpecification { private Tuple2, TimeUnit> expectedResponseTime; private LogDetail responseLogDetail private boolean forceDisableEagerAssert = false + private String onFailMessage private contentParser LogRepository logRepository @@ -311,6 +312,11 @@ class ResponseSpecificationImpl implements FilterableResponseSpecification { this } + ResponseSpecification onFailMessage(String message) { + this.onFailMessage = message + this + } + LogDetail getLogDetail() { responseLogDetail } @@ -490,11 +496,15 @@ class ResponseSpecificationImpl implements FilterableResponseSpecification { fireFailureListeners(response) def errorMessage = errors.collect { it.errorMessage }.join("\n") def s = numberOfErrors > 1 ? "s" : "" - throw new AssertionError("$numberOfErrors expectation$s failed.\n$errorMessage") + throw new AssertionError("$numberOfErrors expectation$s failed.\n$errorMessage$formattedOnFailMessage") } } } + private String getFormattedOnFailMessage() { + onFailMessage ? "\nOn fail message: $onFailMessage" : "" + } + private void fireFailureListeners(Response response) { config.getFailureConfig().getFailureListeners().each { it.onFailure( diff --git a/rest-assured/src/main/java/io/restassured/specification/ResponseSpecification.java b/rest-assured/src/main/java/io/restassured/specification/ResponseSpecification.java index 952f0a439..58e43dec2 100644 --- a/rest-assured/src/main/java/io/restassured/specification/ResponseSpecification.java +++ b/rest-assured/src/main/java/io/restassured/specification/ResponseSpecification.java @@ -1011,4 +1011,16 @@ default ResponseSpecification detachRoot(String pathToDetach) { * @param logDetail The log detail */ ResponseSpecification logDetail(LogDetail logDetail); + + /** + * Add user message to final mismatch description. + *

+ * This is useful when you need to associate a mismatch description with additional user information. For example, in parallel execution. + *

+ * Note, if you want to add a description for certain matching, not for all, you should use something like + * Hamcrest wrapper matcher - {@link org.hamcrest.CoreMatchers#describedAs}. + * + * @param message The user message + */ + ResponseSpecification onFailMessage(String message); } \ No newline at end of file