diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index f8691889f80e..f258dc7d5159 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -167,6 +167,34 @@ ${scribejava.version} test + + org.skyscreamer + jsonassert + ${json.assert.version} + test + + + net.javacrumbs.json-unit + json-unit-assertj + ${json.unit.version} + test + + + net.javacrumbs.json-unit + json-unit + ${json.unit.version} + test + + + uk.org.webcompere + model-assert + ${model.assert.version} + + + uk.co.datumedge + hamcrest-json + ${hamcrest.json.version} + @@ -198,6 +226,10 @@ 3.9.1 2.5.3 5.5.0 + 1.5.3 + 3.4.1 + 1.0.3 + 0.2 \ No newline at end of file diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonUnitTest.java new file mode 100644 index 000000000000..b27b67344d81 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.restassured.assertjson; + +import com.baeldung.restassured.assertjson.WebsitePojo.WebsiteText; +import org.assertj.core.util.Files; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.equalTo; + +class RestAssuredAssertJsonUnitTest extends WireMockTestBase { + + @Test + void whenGetBody_thenCanCompareByFields() { + given() + .get("/static") + .then() + .body("name", equalTo("baeldung")) + .body("type", equalTo("website")) + .body("text.code", equalTo("java")) + .body("text.language", equalTo("english")); + } + + @Test + void whenGetBody_thenCanCompareByWholeString() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThat(body) + .isEqualTo("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCompareByWholeStringIsSensitiveToFieldOrder() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThat(body) + .isNotEqualTo("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByPojo() { + WebsitePojo body = given() + .get("/static") + .then() + .extract() + .body() + .as(WebsitePojo.class); + + assertThat(body) + .isEqualTo(new WebsitePojo("baeldung", "website", new WebsiteText("english", "java"))); + } + + @Disabled("This test cannot predict UUID and timestamp") + @Test + void whenGetBody_thenCannotEasilyHandleUnpredictableValues() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertThat(body) + .isEqualTo("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Disabled("Requires file to be in the exact correct format") + @Test + void whenGetBody_thenCannotEasilyCompareWithFile() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThat(body) + .isEqualTo(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8")); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithHamcrestUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithHamcrestUnitTest.java new file mode 100644 index 000000000000..97aa513c9e61 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithHamcrestUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.restassured.assertjson; + +import net.javacrumbs.jsonunit.core.Option; +import org.assertj.core.util.Files; +import org.junit.jupiter.api.Test; +import java.io.File; + +import static io.restassured.RestAssured.given; +import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; + +import static net.javacrumbs.jsonunit.JsonMatchers.*; +import static uk.org.webcompere.modelassert.json.JsonAssertions.json; + +class RestAssuredAssertJsonWithHamcrestUnitTest extends WireMockTestBase { + + @Test + void whenGetBody_thenCanCompareChangeableFieldsByJsonAssertAgainstFileIgnoringAdditionalFields() { + given() + .get("/build") + .then() + .body(sameJSONAs(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8")).allowingExtraUnexpectedFields()); + } + + @Test + void whenGetBody_thenCanCompareChangeableFieldsByJsonUnitAgainstFileIgnoringAdditionalFields() { + given() + .get("/build") + .then() + .body(jsonEquals(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8")).when(Option.IGNORING_EXTRA_FIELDS)); + } + + @Test + void whenGetBody_thenCanCompareChangeableFieldsByModelAssertionAgainstFileWithPatterns() { + given() + .get("/build") + .then() + .body(json().where() + .keysInAnyOrder() + .path("build").matches("[0-9a-f-]+") + .path("timestamp").matches("[0-9:T.-]+") + .isEqualTo(new File("src/test/resources/expected-build.json"))); + } + +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonAssertUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonAssertUnitTest.java new file mode 100644 index 000000000000..00e9d25cc2e2 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonAssertUnitTest.java @@ -0,0 +1,107 @@ +package com.baeldung.restassured.assertjson; + +import org.assertj.core.util.Files; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.Customization; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.skyscreamer.jsonassert.RegularExpressionValueMatcher; +import org.skyscreamer.jsonassert.comparator.CustomComparator; + +import java.io.File; + +import static io.restassured.RestAssured.given; + +class RestAssuredAssertJsonWithJsonAssertUnitTest extends WireMockTestBase { + + @Test + void whenGetBody_thenCanCompareByJsonAssert() throws Exception { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}", body, JSONCompareMode.STRICT); + } + + @Test + void whenGetBody_thenCanCompareByJsonAssertWithFieldsInDifferentOrder() throws Exception { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}", body, JSONCompareMode.STRICT); + } + + @Test + void whenGetBody_thenCanCompareByJsonAssertAgainstFile() throws Exception { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8"), body, JSONCompareMode.STRICT); + } + + @Test + void whenGetBody_thenCanCompareByJsonAssertAgainstFileDifferentOrder() throws Exception { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals(Files.contentOf(new File("src/test/resources/expected-website-different-field-order.json"), "UTF-8"), body, JSONCompareMode.STRICT); + } + + @Disabled("This doesn't work because the file contains fields that change every time") + @Test + void whenGetBody_thenCannotCompareChangeableFieldsByJsonAssertAgainstFile() throws Exception { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals(Files.contentOf(new File("src/test/resources/expected-build.json"), "UTF-8"), body, JSONCompareMode.STRICT); + } + + @Test + void whenGetBody_thenCanCompareChangeableFieldsByIgnoringExtraFields() throws Exception { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8"), body, JSONCompareMode.LENIENT); + } + + @Test + void whenGetBody_thenCanCompareChangeableFieldsByJsonAssertAgainstFile() throws Exception { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + JSONAssert.assertEquals(Files.contentOf(new File("src/test/resources/expected-build.json"), "UTF-8"), body, + new CustomComparator(JSONCompareMode.STRICT, + new Customization("build", + new RegularExpressionValueMatcher<>("[0-9a-f-]+")), + new Customization("timestamp", + new RegularExpressionValueMatcher<>(".+")))); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonUnitUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonUnitUnitTest.java new file mode 100644 index 000000000000..247bf24e30c3 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithJsonUnitUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.restassured.assertjson; + +import net.javacrumbs.jsonunit.core.Option; +import org.assertj.core.util.Files; +import org.junit.jupiter.api.Test; + + +import java.io.File; + +import static io.restassured.RestAssured.given; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; + +class RestAssuredAssertJsonWithJsonUnitUnitTest extends WireMockTestBase { + + @Test + void whenGetBody_thenCanCompareByJsonUnit() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .isEqualTo("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByJsonUnitWithFieldsInDifferentOrder() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .isEqualTo("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByJsonUnitAgainstFile() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .isEqualTo(Files.contentOf(new File("src/test/resources/expected-website.json"), "UTF-8")); + } + + @Test + void whenGetBody_thenCanCompareByJsonUnitAgainstFileDifferentOrder() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .isEqualTo(Files.contentOf(new File("src/test/resources/expected-website-different-field-order.json"), "UTF-8")); + } + + @Test + void whenGetBody_thenCanCompareByJsonUnitAgainstUnpredictableFieldsByIgnoringExtraFields() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .when(Option.IGNORING_EXTRA_FIELDS) + .isEqualTo("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByJsonUnitAgainstUnpredictableFields() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertThatJson(body) + .isEqualTo("{\"build\":\"${json-unit.regex}[0-9a-f-]+\",\"timestamp\":\"${json-unit.any-string}\",\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithModelAssertUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithModelAssertUnitTest.java new file mode 100644 index 000000000000..9729c33e8721 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/RestAssuredAssertJsonWithModelAssertUnitTest.java @@ -0,0 +1,116 @@ +package com.baeldung.restassured.assertjson; + +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static io.restassured.RestAssured.given; +import static uk.org.webcompere.modelassert.json.JsonAssertions.assertJson; + +class RestAssuredAssertJsonWithModelAssertUnitTest extends WireMockTestBase { + + @Test + void whenGetBody_thenCanCompareByModelAssert() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .isEqualTo("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertWithFieldsInDifferentOrder() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .where() + .keysInAnyOrder() + .isEqualTo("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertAgainstFile() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .isEqualTo(new File("src/test/resources/expected-website.json")); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertAgainstFileDifferentOrder() { + String body = given() + .get("/static") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .where() + .keysInAnyOrder() + .isEqualTo(new File("src/test/resources/expected-website-different-field-order.json")); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertAgainstUnpredictableFieldsByIgnoringExtraFields() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .where() + .objectContains() + .isEqualTo("{\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertAgainstUnpredictableFields() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .where() + .keysInAnyOrder() + .path("build").matches("[0-9a-f-]+") + .path("timestamp").matches("[0-9:T.-]+") + .isEqualTo("{\"build\":\"build\",\"timestamp\":\"timestamps\",\"type\":\"website\",\"name\":\"baeldung\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"); + } + + @Test + void whenGetBody_thenCanCompareByModelAssertUnpredictableFieldsAgainstFile() { + String body = given() + .get("/build") + .then() + .extract() + .body() + .asString(); + + assertJson(body) + .where() + .keysInAnyOrder() + .path("build").matches("[0-9a-f-]+") + .path("timestamp").matches("[0-9:T.-]+") + .isEqualTo(new File("src/test/resources/expected-build.json")); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WebsitePojo.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WebsitePojo.java new file mode 100644 index 000000000000..ff77ebfbe3a3 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WebsitePojo.java @@ -0,0 +1,105 @@ +package com.baeldung.restassured.assertjson; + +import java.util.Objects; + +public class WebsitePojo { + public static class WebsiteText { + private String language; + private String code; + + public WebsiteText() { + } + + public WebsiteText(String language, String code) { + this.language = language; + this.code = code; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + WebsiteText that = (WebsiteText) o; + return Objects.equals(language, that.language) && Objects.equals(code, that.code); + } + + @Override + public int hashCode() { + return Objects.hash(language, code); + } + } + + private String name; + private String type; + private WebsiteText text; + + public WebsitePojo() { + } + + public WebsitePojo(String name, String type, WebsiteText text) { + this.name = name; + this.type = type; + this.text = text; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public WebsiteText getText() { + return text; + } + + public void setText(WebsiteText text) { + this.text = text; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + WebsitePojo that = (WebsitePojo) o; + return Objects.equals(name, that.name) && Objects.equals(type, that.type) && Objects.equals(text, that.text); + } + + @Override + public int hashCode() { + return Objects.hash(name, type, text); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WireMockTestBase.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WireMockTestBase.java new file mode 100644 index 000000000000..be45e8508323 --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/assertjson/WireMockTestBase.java @@ -0,0 +1,33 @@ +package com.baeldung.restassured.assertjson; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import io.restassured.RestAssured; +import org.junit.jupiter.api.BeforeEach; + +import java.time.LocalDateTime; +import java.util.UUID; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; + +@WireMockTest +abstract class WireMockTestBase { + + @BeforeEach + void beforeEach(WireMockRuntimeInfo wmRuntimeInfo) { + stubFor(get("/static").willReturn( + aResponse() + .withStatus(200) + .withHeader("content-type", "application/json") + .withBody("{\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"))); + + stubFor(get("/build").willReturn( + aResponse() + .withStatus(200) + .withHeader("content-type", "application/json") + .withBody("{\"build\":\"" + UUID.randomUUID() + "\",\"timestamp\":\"" + LocalDateTime.now() + "\",\"name\":\"baeldung\",\"type\":\"website\",\"text\":{\"language\":\"english\",\"code\":\"java\"}}"))); + + RestAssured.port = wmRuntimeInfo.getHttpPort(); + } + +} diff --git a/testing-modules/rest-assured/src/test/resources/expected-build.json b/testing-modules/rest-assured/src/test/resources/expected-build.json new file mode 100644 index 000000000000..53d2b11d3cdd --- /dev/null +++ b/testing-modules/rest-assured/src/test/resources/expected-build.json @@ -0,0 +1,10 @@ +{ + "build": "360dac90-38bc-4430-bbc3-a46091aea135", + "timestamp": "2024-09-09T22:33:46.691667", + "name": "baeldung", + "type": "website", + "text": { + "language": "english", + "code": "java" + } +} \ No newline at end of file diff --git a/testing-modules/rest-assured/src/test/resources/expected-website-different-field-order.json b/testing-modules/rest-assured/src/test/resources/expected-website-different-field-order.json new file mode 100644 index 000000000000..3ca55c282af6 --- /dev/null +++ b/testing-modules/rest-assured/src/test/resources/expected-website-different-field-order.json @@ -0,0 +1,8 @@ +{ + "text": { + "language": "english", + "code": "java" + }, + "type": "website", + "name": "baeldung" +} \ No newline at end of file diff --git a/testing-modules/rest-assured/src/test/resources/expected-website.json b/testing-modules/rest-assured/src/test/resources/expected-website.json new file mode 100644 index 000000000000..402e9b98c08c --- /dev/null +++ b/testing-modules/rest-assured/src/test/resources/expected-website.json @@ -0,0 +1,8 @@ +{ + "name": "baeldung", + "type": "website", + "text": { + "language": "english", + "code": "java" + } +} \ No newline at end of file