diff --git a/pom.xml b/pom.xml index 9390a6a..74f80ee 100644 --- a/pom.xml +++ b/pom.xml @@ -61,9 +61,11 @@ 1.4.12 2.11.0 8.32 + + 5.7.0 4.13.2 - 2.2 + 3.24.2 3.8.1 11 @@ -217,16 +219,23 @@ - org.hamcrest - hamcrest - ${hamcrest.version} + com.google.inject + guice + ${guice.version} test - com.google.inject - guice - ${guice.version} + org.assertj + assertj-core + ${assertj.version} + test + + + + io.vertx + vertx-web-client + ${vertx.version} test diff --git a/src/main/java/com/dream11/rest/AbstractRestVerticle.java b/src/main/java/com/dream11/rest/AbstractRestVerticle.java index 5235770..4154854 100644 --- a/src/main/java/com/dream11/rest/AbstractRestVerticle.java +++ b/src/main/java/com/dream11/rest/AbstractRestVerticle.java @@ -13,6 +13,8 @@ import io.reactivex.rxjava3.core.Single; import io.vertx.core.http.HttpServerOptions; import io.vertx.rxjava3.core.AbstractVerticle; +import io.vertx.rxjava3.core.Context; +import io.vertx.rxjava3.core.RxHelper; import io.vertx.rxjava3.core.http.HttpServer; import io.vertx.rxjava3.core.http.HttpServerRequest; import io.vertx.rxjava3.ext.web.Router; @@ -69,8 +71,9 @@ private Single startHttpServer() { .map(HttpServerRequest::pause) .onBackpressureDrop(req -> { log.error("Dropping request with status 503"); - req.response().setStatusCode(503).end(); + req.getDelegate().response().setStatusCode(503).end(); }) + .observeOn(RxHelper.scheduler(new Context(this.context))) // For backpressure .doOnNext(req -> { if (req.path().matches("/swagger(.*)")) { router.handle(req); diff --git a/src/test/java/com/dream11/rest/RestApiIT.java b/src/test/java/com/dream11/rest/RestApiIT.java index 558cd3f..4cb8f97 100644 --- a/src/test/java/com/dream11/rest/RestApiIT.java +++ b/src/test/java/com/dream11/rest/RestApiIT.java @@ -1,124 +1,161 @@ package com.dream11.rest; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.reactivex.rxjava3.core.Single; import io.vertx.core.json.JsonObject; import io.vertx.junit5.VertxExtension; +import io.vertx.rxjava3.core.MultiMap; +import io.vertx.rxjava3.core.Vertx; +import io.vertx.rxjava3.core.buffer.Buffer; +import io.vertx.rxjava3.ext.web.client.HttpResponse; +import io.vertx.rxjava3.ext.web.client.WebClient; +import java.util.ArrayList; +import java.util.List; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; - @ExtendWith({VertxExtension.class, Setup.class}) @Slf4j class RestApiIT { - final CloseableHttpClient httpClient = HttpClients.createDefault(); + final WebClient webClient = WebClient.create(Vertx.vertx()); @Test - void nullHeaderTest() throws IOException { + void nullHeaderTest() { // arrange - String uri = String.format("http://127.0.0.1:%s%s/1?testFilter=query&double=1.1&float=1.1&integer=1&long=1", - Constants.APPLICATION_PORT, Constants.VALIDATION_ROUTE_PATH); + String path = String.format("%s/1?testFilter=query&double=1.1&float=1.1&integer=1&long=1", Constants.VALIDATION_ROUTE_PATH); // act - HttpResponse response = httpClient.execute(new HttpGet(uri)); + int statusCode = this.makeGetRequest(path) + .map(HttpResponse::statusCode) + .blockingGet(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(400)); + assertThat(statusCode).isEqualTo(400); } @Test - void nullQueryParamTest() throws IOException { + void nullQueryParamTest() { // arrange - String uri = String.format("http://127.0.0.1:%s%s/1", Constants.APPLICATION_PORT, Constants.VALIDATION_ROUTE_PATH); - HttpGet request = new HttpGet(uri); - request.setHeader("testHeader", "1"); + String path = String.format("%s/1", Constants.VALIDATION_ROUTE_PATH); + MultiMap headers = MultiMap.caseInsensitiveMultiMap().add("testHeader", "1"); // act - HttpResponse response = httpClient.execute(request); + int statusCode = this.makeGetRequest(path, headers) + .map(HttpResponse::statusCode) + .blockingGet(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(400)); + assertThat(statusCode).isEqualTo(400); } @ParameterizedTest @CsvSource({"/class", "/method"}) - void timeoutAnnotationTest(String path) throws IOException { + void timeoutAnnotationTest(String param) { // arrange - String uri = String.format("http://127.0.0.1:%s%s%s", Constants.APPLICATION_PORT, Constants.TIMEOUT_ROUTE_PATH, path); + String path = String.format("%s%s", Constants.TIMEOUT_ROUTE_PATH, param); // act - HttpResponse response = httpClient.execute(new HttpGet(uri)); + int statusCode = this.makeGetRequest(path) + .map(HttpResponse::statusCode) + .blockingGet(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(503)); + assertThat(statusCode).isEqualTo(503); } @ParameterizedTest @CsvSource({"integer", "long", "float", "double"}) - void typeTypeValidationParamTest(String param) throws IOException { + void typeTypeValidationParamTest(String param) { + // arrange + String path = String.format("%s/1?testFilter=query&%s=param", Constants.VALIDATION_ROUTE_PATH, param); + MultiMap headers = MultiMap.caseInsensitiveMultiMap().add("testHeader", "1"); + // act + HttpResponse response = this.makeGetRequest(path, headers) + .blockingGet(); + JsonObject responseBody = response.bodyAsJsonObject(); + // assert + assertThat(response.statusCode()).isEqualTo(400); + assertThat(responseBody.getJsonObject("error").getString("code")).isEqualTo("BAD_REQUEST"); + assertThat(responseBody.getJsonObject("error").getString("message")).isEqualTo( + String.format("Query param '%s' must be %s", param, param)); + } + + @Test + void validateBodyTest() { // arrange - String uri = - String.format("http://127.0.0.1:%s%s/1?testFilter=query&%s=param", Constants.APPLICATION_PORT, Constants.VALIDATION_ROUTE_PATH, - param); - HttpGet request = new HttpGet(uri); - request.setHeader("testHeader", "1"); + String path = String.format("%s", Constants.VALIDATION_ROUTE_PATH); + JsonObject body = new JsonObject().put("resourceId", "Hello"); // act - HttpResponse response = httpClient.execute(request); - JsonObject responseBody = new JsonObject(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8)); + HttpResponse response = this.makePostRequest(path, body) + .blockingGet(); + JsonObject responseBody = response.bodyAsJsonObject(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(400)); - assertThat(responseBody.getJsonObject("error").getString("code"), equalTo("BAD_REQUEST")); - assertThat(responseBody.getJsonObject("error").getString("message"), - equalTo(String.format("Query param '%s' must be %s", param, param))); + assertThat(response.statusCode()).isEqualTo(400); + assertThat(responseBody.getJsonObject("error").getString("code")).isEqualTo("BAD_REQUEST"); + assertThat(responseBody.getJsonObject("error").getString("message")).isEqualTo("resourceId must be integer"); } @Test - void validateBodyTest() throws IOException { + void positiveBodyTest() { // arrange - String uri = String.format("http://127.0.0.1:%s%s", Constants.APPLICATION_PORT, Constants.VALIDATION_ROUTE_PATH); - HttpPost request = new HttpPost(uri); - request.setHeader("Content-type", "application/json"); - JsonObject json = new JsonObject().put("resourceId", "Hello"); - request.setEntity(new StringEntity(json.toString())); + String path = String.format("%s", Constants.VALIDATION_ROUTE_PATH); + JsonObject body = new JsonObject().put("resourceId", "1"); // act - HttpResponse response = httpClient.execute(request); - JsonObject responseBody = new JsonObject(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8)); + HttpResponse response = this.makePostRequest(path, body) + .blockingGet(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(400)); - assertThat(responseBody.getJsonObject("error").getString("code"), equalTo("BAD_REQUEST")); - assertThat(responseBody.getJsonObject("error").getString("message"), equalTo("resourceId must be integer")); + assertThat(response.statusCode()).isEqualTo(200); } @Test - void positiveBodyTest() throws IOException { + void routeNotFoundTest() { // arrange - String uri = String.format("http://127.0.0.1:%s%s", Constants.APPLICATION_PORT, Constants.VALIDATION_ROUTE_PATH); - HttpPost request = new HttpPost(uri); - request.setHeader("Content-type", "application/json"); - JsonObject json = new JsonObject().put("resourceId", "1"); - request.setEntity(new StringEntity(json.toString())); + String path = "/nonexistent"; // act - HttpResponse response = httpClient.execute(request); + int statusCode = this.makeGetRequest(path) + .map(HttpResponse::statusCode) + .blockingGet(); // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); + assertThat(statusCode).isEqualTo(404); } + @Test - void routeNotFoundTest() throws IOException { + @SneakyThrows + void testBackPressure() { // arrange - String uri = String.format("http://127.0.0.1:%s%s", Constants.APPLICATION_PORT, "/nonexistent"); + JsonObject body = JsonObject.of("resourceId", "1"); + List>> responseSingles = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + responseSingles.add(this.makePostRequest(Constants.VALIDATION_ROUTE_PATH, body)); + } + // act - HttpResponse response = httpClient.execute(new HttpGet(uri)); + List statusCodes = Single.merge(responseSingles) + .map(HttpResponse::statusCode) + .toList() + .blockingGet(); + // assert - assertThat(response.getStatusLine().getStatusCode(), equalTo(404)); + assertThat(statusCodes).contains(200, 503); } + private Single> makePostRequest(String path, JsonObject body) { + String uri = String.format("http://127.0.0.1:%s%s", Constants.APPLICATION_PORT, path); + return this.webClient.postAbs(uri) + .putHeader("Content-type", "application/json") + .rxSendJsonObject(body); + } + + private Single> makeGetRequest(String path, MultiMap headers) { + String uri = String.format("http://127.0.0.1:%s%s", Constants.APPLICATION_PORT, path); + return this.webClient.getAbs(uri) + .putHeaders(headers) + .rxSend(); + } + + private Single> makeGetRequest(String path) { + return makeGetRequest(path, MultiMap.caseInsensitiveMultiMap()); + } } diff --git a/src/test/java/com/dream11/rest/Setup.java b/src/test/java/com/dream11/rest/Setup.java index 0bd58e5..3708eee 100644 --- a/src/test/java/com/dream11/rest/Setup.java +++ b/src/test/java/com/dream11/rest/Setup.java @@ -4,6 +4,7 @@ import com.dream11.rest.util.SharedDataUtil; import com.dream11.rest.verticle.RestVerticle; import com.google.inject.Guice; +import io.vertx.core.DeploymentOptions; import io.vertx.rxjava3.core.Vertx; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.extension.AfterAllCallback; @@ -24,7 +25,8 @@ public void beforeAll(ExtensionContext extensionContext) { GuiceInjector injector = new GuiceInjector(Guice.createInjector()); SharedDataUtil.setInstance(vertx.getDelegate(), injector); final String verticleName = RestVerticle.class.getName(); - String deploymentId = this.vertx.rxDeployVerticle(injector.getInstance(RestVerticle.class)) + System.setProperty("rx3.buffer-size", "1"); // Set rxjava buffer size + String __ = this.vertx.rxDeployVerticle(injector.getInstance(RestVerticle.class), new DeploymentOptions().setInstances(1)) .doOnError(error -> log.error("Error in deploying verticle : {}", verticleName, error)) .doOnSuccess(v -> log.info("Deployed verticle : {}", verticleName)).blockingGet(); } diff --git a/src/test/java/com/dream11/rest/exception/RestExceptionTest.java b/src/test/java/com/dream11/rest/exception/RestExceptionTest.java index c0e29c1..a003b59 100644 --- a/src/test/java/com/dream11/rest/exception/RestExceptionTest.java +++ b/src/test/java/com/dream11/rest/exception/RestExceptionTest.java @@ -2,8 +2,8 @@ import org.junit.jupiter.api.Test; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; + class RestExceptionTest { @Test @@ -17,13 +17,13 @@ void testRestException() { RestException restException = new RestException(restError); RestException restExceptionWithCause = new RestException(restError, cause); // assert - assertThat(restException.getMessage(), equalTo(restError.getErrorMessage())); - assertThat(restException.getHttpStatusCode(), equalTo(restError.getHttpStatusCode())); - assertThat(restException.getErrorCode(), equalTo(restError.getErrorCode())); + assertThat(restException.getMessage()).isEqualTo(restError.getErrorMessage()); + assertThat(restException.getHttpStatusCode()).isEqualTo(restError.getHttpStatusCode()); + assertThat(restException.getErrorCode()).isEqualTo(restError.getErrorCode()); - assertThat(restExceptionWithCause.getMessage(), equalTo(restError.getErrorMessage())); - assertThat(restExceptionWithCause.getHttpStatusCode(), equalTo(restError.getHttpStatusCode())); - assertThat(restExceptionWithCause.getErrorCode(), equalTo(restError.getErrorCode())); - assertThat(restExceptionWithCause.getCause(), equalTo(cause)); + assertThat(restExceptionWithCause.getMessage()).isEqualTo(restError.getErrorMessage()); + assertThat(restExceptionWithCause.getHttpStatusCode()).isEqualTo(restError.getHttpStatusCode()); + assertThat(restExceptionWithCause.getErrorCode()).isEqualTo(restError.getErrorCode()); + assertThat(restExceptionWithCause.getCause()).isEqualTo(cause); } } diff --git a/src/test/java/com/dream11/rest/util/AnnotationUtilTest.java b/src/test/java/com/dream11/rest/util/AnnotationUtilTest.java index 24cbf9e..e666cf4 100644 --- a/src/test/java/com/dream11/rest/util/AnnotationUtilTest.java +++ b/src/test/java/com/dream11/rest/util/AnnotationUtilTest.java @@ -1,16 +1,15 @@ package com.dream11.rest.util; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.equalTo; - import com.dream11.rest.Constants; import com.dream11.rest.route.TimeoutRoute; import com.dream11.rest.route.ValidationCheckRoute; import jakarta.ws.rs.Path; +import org.junit.jupiter.api.Test; + import java.lang.annotation.Annotation; import java.util.List; -import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; class AnnotationUtilTest { @Test @@ -20,8 +19,9 @@ void testAnnotatedClasses() { // act List> classes = AnnotationUtil.getClassesWithAnnotation(Constants.TEST_PACKAGE_NAME, annotation); // assert - assertThat(classes.size(), equalTo(2)); - assertThat(classes, containsInAnyOrder(ValidationCheckRoute.class, TimeoutRoute.class)); + assertThat(classes) + .hasSize(2) + .contains(ValidationCheckRoute.class, TimeoutRoute.class); } } diff --git a/src/test/java/com/dream11/rest/util/ExceptionUtilTest.java b/src/test/java/com/dream11/rest/util/ExceptionUtilTest.java index 42e99a1..bcd49dd 100644 --- a/src/test/java/com/dream11/rest/util/ExceptionUtilTest.java +++ b/src/test/java/com/dream11/rest/util/ExceptionUtilTest.java @@ -1,7 +1,7 @@ package com.dream11.rest.util; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; + +import static org.assertj.core.api.Assertions.assertThat; import com.dream11.rest.exception.RestAppError; import com.dream11.rest.exception.RestError; @@ -17,10 +17,10 @@ void testParseThrowable() { // act Throwable throwable = ExceptionUtil.parseThrowable(exception); // assert - assertThat(throwable.getClass(), equalTo(RestException.class)); - assertThat(throwable.getMessage(), equalTo(exception.getMessage())); - assertThat(((RestException) throwable).getHttpStatusCode(), equalTo(exception.getHttpStatusCode())); - assertThat(((RestException) throwable).getErrorCode(), equalTo(exception.getErrorCode())); + assertThat(throwable.getClass()).isEqualTo(RestException.class); + assertThat(throwable.getMessage()).isEqualTo(exception.getMessage()); + assertThat(((RestException) throwable).getHttpStatusCode()).isEqualTo(exception.getHttpStatusCode()); + assertThat(((RestException) throwable).getErrorCode()).isEqualTo(exception.getErrorCode()); } @Test @@ -30,11 +30,11 @@ void testGenericParseThrowable() { // act Throwable throwable = ExceptionUtil.parseThrowable(new RuntimeException(message)); // assert - assertThat(throwable.getClass(), equalTo(RestException.class)); - assertThat(((RestException) throwable).getHttpStatusCode(), equalTo(RestErrorEnum.UNKNOWN_EXCEPTION.getHttpStatusCode())); - assertThat(((RestException) throwable).getErrorCode(), equalTo(RestErrorEnum.UNKNOWN_EXCEPTION.getErrorCode())); - assertThat(throwable.getMessage(), equalTo(RestErrorEnum.UNKNOWN_EXCEPTION.getErrorMessage())); - assertThat(throwable.getCause().getMessage(), equalTo(message)); + assertThat(throwable.getClass()).isEqualTo(RestException.class); + assertThat(((RestException) throwable).getHttpStatusCode()).isEqualTo(RestErrorEnum.UNKNOWN_EXCEPTION.getHttpStatusCode()); + assertThat(((RestException) throwable).getErrorCode()).isEqualTo(RestErrorEnum.UNKNOWN_EXCEPTION.getErrorCode()); + assertThat(throwable.getMessage()).isEqualTo(RestErrorEnum.UNKNOWN_EXCEPTION.getErrorMessage()); + assertThat(throwable.getCause().getMessage()).isEqualTo(message); } @Test @@ -47,10 +47,10 @@ void testGetException() { RestException restException = ExceptionUtil.getException(restError, "Something went wrong", "Error message"); // assert - assertThat(restException.getHttpStatusCode(), equalTo(restError.getHttpStatusCode())); - assertThat(restException.getErrorCode(), equalTo(restError.getErrorCode())); - assertThat(restException.getMessage(), equalTo(errorMessage)); - assertThat(restException.getMessage(), equalTo(restException.getErrorMessage())); + assertThat(restException.getHttpStatusCode()).isEqualTo(restError.getHttpStatusCode()); + assertThat(restException.getErrorCode()).isEqualTo(restError.getErrorCode()); + assertThat(restException.getMessage()).isEqualTo(errorMessage); + assertThat(restException.getMessage()).isEqualTo(restException.getErrorMessage()); } } diff --git a/src/test/java/com/dream11/rest/util/RestUtilTest.java b/src/test/java/com/dream11/rest/util/RestUtilTest.java index 8e334fe..7e913eb 100644 --- a/src/test/java/com/dream11/rest/util/RestUtilTest.java +++ b/src/test/java/com/dream11/rest/util/RestUtilTest.java @@ -1,15 +1,12 @@ package com.dream11.rest.util; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import com.fasterxml.jackson.core.JsonProcessingException; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; - import java.util.Arrays; import java.util.List; - -import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; class RestUtilTest { @@ -21,7 +18,7 @@ void testListObjectToString() throws JsonProcessingException { // act String listToString = RestUtil.objectToString(integerList); // assert - assertThat(listToString, Matchers.equalTo("[1,2,3]")); + assertThat(listToString).isEqualTo("[1,2,3]"); } @Test @@ -29,7 +26,7 @@ void testStringObjectToString() throws JsonProcessingException { // arrange String message = "MESSAGE"; // assert - assertThat(RestUtil.objectToString(message), Matchers.equalTo(message)); + assertThat(RestUtil.objectToString(message)).isEqualTo(message); } @Test @@ -39,8 +36,8 @@ void testJsonObjectToString() throws JsonProcessingException { // act String jsonObjectString = RestUtil.objectToString(jsonObject); // assert - assertThat(jsonObjectString, Matchers.equalTo(jsonObject.toString())); - assertThat(RestUtil.objectToString(jsonObject), Matchers.equalTo(jsonObject.toString())); + assertThat(jsonObjectString).isEqualTo(jsonObject.toString()); + assertThat(RestUtil.objectToString(jsonObject)).isEqualTo(jsonObject.toString()); } @Test @@ -50,6 +47,6 @@ void testJsonArrayToString() throws JsonProcessingException { // act String jsonArrayString = RestUtil.objectToString(jsonArray); // assert - assertThat(jsonArrayString, Matchers.equalTo(jsonArray.toString())); + assertThat(jsonArrayString).isEqualTo(jsonArray.toString()); } }