diff --git a/build.gradle b/build.gradle index 0242b8b..c7ca048 100644 --- a/build.gradle +++ b/build.gradle @@ -1,18 +1,25 @@ -import org.apache.tools.ant.filters.ReplaceTokens import org.springframework.cloud.contract.verifier.config.TestFramework +//plugins plugins { - id 'java' - id 'org.springframework.boot' version '2.5.4' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'org.springframework.cloud.contract' version '3.0.3' - id 'com.gorylenko.gradle-git-properties' version '2.3.1' -//doc - id 'org.springdoc.openapi-gradle-plugin' version '1.3.3' - id 'org.asciidoctor.jvm.convert' version '3.3.2' - id 'com.github.johnrengelman.processes' version '0.5.0' -// id 'maven-publish' + // Core + id 'jacoco' + + // Spring + id 'org.springframework.boot' + id 'io.spring.dependency-management' + id 'org.springframework.cloud.contract' + id 'com.gorylenko.gradle-git-properties' + + //doc + id 'org.springdoc.openapi-gradle-plugin' + id 'org.asciidoctor.jvm.convert' + id 'com.github.johnrengelman.processes' + + // Tests + id 'com.adarshr.test-logger' } + group = 'com.neueda.java-blocking-microservice-chassis' description = 'Java Blocking Microservice Chassis' version = '0.0.1-SNAPSHOT' @@ -22,6 +29,8 @@ ext { snippetsDir = file 'build/generated-snippets' springCloudVersion = '2020.0.3' springDocVersion = '1.5.10' + springRestdocsVersion = '2.0.5.RELEASE' + springBlockSwitchVersion = '0.6.0' testcontainersVersion = '1.15.3' managementPort = '8081' } @@ -53,46 +62,63 @@ configurations { } repositories { - mavenCentral() - maven { url 'https://repo.spring.io/release' } -} -repositories { + mavenCentral() maven { url 'https://repo.spring.io/release' } } -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-actuator:2.5.3' - implementation 'org.springframework.cloud:spring-cloud-starter-sleuth:3.0.3' - implementation 'org.liquibase:liquibase-core:4.3.5' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa:2.5.3' - implementation 'org.projectlombok:lombok:1.18.20' - implementation 'org.springframework.boot:spring-boot-starter-validation:2.5.3' - implementation 'org.springframework.boot:spring-boot-configuration-processor:2.5.3' - implementation 'org.springframework.boot:spring-boot-starter-web:2.5.3' - implementation 'org.springdoc:springdoc-openapi-ui:1.5.10' - implementation 'jakarta.validation:jakarta.validation-api:2.0.2' - implementation 'io.swagger.core.v3:swagger-models:2.1.9' - implementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' - runtimeOnly 'org.springframework.boot:spring-boot-devtools:2.5.3' - runtimeOnly 'com.h2database:h2:1.4.200' - testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.3' - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc:2.0.5.RELEASE' - testImplementation 'io.rest-assured:spring-mock-mvc:4.3.3' - testImplementation 'org.postgresql:postgresql:42.2.23' - testImplementation 'org.testcontainers:postgresql:1.16.0' - testImplementation 'org.testcontainers:junit-jupiter:1.16.0' - testImplementation 'org.testcontainers:jdbc:1.16.0' - testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier:3.0.3' - testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner:3.0.3' -} dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}" + mavenBom"org.springframework:spring-context:${springVersion}" + mavenBom"org.springdoc:springdoc-openapi-ui:${springdocOpenapiuiVersion}" } + } +dependencies { + //Used to monitoring and manage application + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' + + // used for Persistence data + implementation 'org.liquibase:liquibase-core' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + //API Documentation + implementation 'org.springdoc:springdoc-openapi-ui:1.5.10' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + + //testing + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'io.rest-assured:spring-mock-mvc' + implementation 'jakarta.validation:jakarta.validation-api' + implementation 'io.swagger.core.v3:swagger-models' + + // Development Tools used to develop an application + annotationProcessor 'org.projectlombok:lombok' + annotationProcessor 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-configuration-processor' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'org.springframework.boot:spring-boot-devtools' + + //used to build Restfull web + implementation 'org.springframework.boot:spring-boot-starter-web' + + //Test Containers + intTestRuntimeOnly 'org.postgresql:postgresql' + intTestImplementation 'org.testcontainers:postgresql' + intTestRuntimeOnly 'org.testcontainers:junit-jupiter' + intTestImplementation 'org.testcontainers:jdbc' + + //Contract Testing + testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier' + testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner' + implementation 'org.junit.jupiter:junit-jupiter-api' + + +} processResources { eachFile { if (relativeSourcePath ==~ /^(config\/)?application(-\w+)?.(ya?ml|properties)$/) { @@ -154,8 +180,27 @@ contractTest { test { useJUnitPlatform { excludeEngines 'junit-vintage' } outputs.dir snippetsDir -} - + finalizedBy jacocoTestReport +} +testlogger { + theme 'mocha' + showExceptions true + showStackTraces true + showFullStackTraces false + showCauses true + slowThreshold 2000 + showSummary true + showSimpleNames false + showPassed true + showSkipped true + showFailed true + showStandardStreams false + showPassedStandardStreams true + showSkippedStandardStreams true + showFailedStandardStreams true + logLevel 'lifecycle' +} +jacocoTestReport.dependsOn test asciidoctor { // By convention it sets // sourceDir to src/docs/asciidoc diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..14514cd --- /dev/null +++ b/gradle.properties @@ -0,0 +1,19 @@ +org.gradle.daemon=true +org.gradle.caching=false + +# Spring Plugin Versions +sprinbBootVersion=2.5.4 +springVersion = 5.0.3.RELEASE +springDependencyManagementVersion=1.0.11.RELEASE +springContractVersion=3.0.3 +gitPropertiesVersion=2.3.1 + +# Docs Plugin Versions +gradleProcessesVersion=0.5.0 +springdocOpenapiVersion=1.3.3 +asciidoctorConvertVersion=3.3.2 +springdocOpenapiuiVersion=1.5.10 + +# Tests Plugin Versions +testLoggerVersion=3.0.0 + diff --git a/settings.gradle b/settings.gradle index 1dd348f..d00cc53 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,23 @@ +pluginManagement { +//plugins + plugins { + // Core + id 'jacoco' + + // Spring + id 'org.springframework.boot' version sprinbBootVersion + id 'io.spring.dependency-management' version springDependencyManagementVersion + id 'org.springframework.cloud.contract' version springContractVersion + id 'com.gorylenko.gradle-git-properties' version gitPropertiesVersion + + //doc + id 'org.springdoc.openapi-gradle-plugin' version springdocOpenapiVersion + id 'org.springdoc.openapi-ui' version springdocOpenapiuiVersion + id 'org.asciidoctor.jvm.convert' version asciidoctorConvertVersion + id 'com.github.johnrengelman.processes' version gradleProcessesVersion + + // Tests + id 'com.adarshr.test-logger' version testLoggerVersion + } +} rootProject.name = 'java-blocking-microservice-chassis' diff --git a/src/test/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationTests.java b/src/intTest/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationIT.java similarity index 77% rename from src/test/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationTests.java rename to src/intTest/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationIT.java index 25190d2..918123d 100644 --- a/src/test/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationTests.java +++ b/src/intTest/java/com/neueda/blocking/chassis/JavaBlockingMicroserviceChassisApplicationIT.java @@ -4,10 +4,11 @@ import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest -class JavaBlockingMicroserviceChassisApplicationTests { +class JavaBlockingMicroserviceChassisApplicationIT { @Test void contextLoads() { + } } diff --git a/src/test/java/com/neueda/blocking/chassis/PostgresTestContainer.java b/src/intTest/java/com/neueda/blocking/chassis/PostgresTestContainer.java similarity index 99% rename from src/test/java/com/neueda/blocking/chassis/PostgresTestContainer.java rename to src/intTest/java/com/neueda/blocking/chassis/PostgresTestContainer.java index 739943d..5702794 100644 --- a/src/test/java/com/neueda/blocking/chassis/PostgresTestContainer.java +++ b/src/intTest/java/com/neueda/blocking/chassis/PostgresTestContainer.java @@ -6,7 +6,6 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; - @Slf4j public class PostgresTestContainer { @@ -24,4 +23,4 @@ private static void setDatasourceProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.username", postgresContainer::getUsername); registry.add("spring.datasource.password", postgresContainer::getPassword); } -} +} \ No newline at end of file diff --git a/src/test/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java b/src/intTest/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java similarity index 97% rename from src/test/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java rename to src/intTest/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java index 06213e1..5faa409 100644 --- a/src/test/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java +++ b/src/intTest/java/com/neueda/blocking/chassis/repository/ChassisRepositoryIT.java @@ -15,7 +15,6 @@ import java.util.Set; import static org.assertj.core.api.BDDAssertions.then; - @DataJpaTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class ChassisRepositoryIT extends PostgresTestContainer { @@ -41,7 +40,7 @@ void shouldFindByName() { List result = underTest.findByName(name); //then - BDDAssertions.then(result).isEqualTo(expected); + BDDAssertions.then(result).isEqualTo(expected); } @Test diff --git a/src/test/java/com/neueda/blocking/chassis/service/ChassisServiceTests.java b/src/intTest/java/com/neueda/blocking/chassis/service/ChassisServiceIT.java similarity index 95% rename from src/test/java/com/neueda/blocking/chassis/service/ChassisServiceTests.java rename to src/intTest/java/com/neueda/blocking/chassis/service/ChassisServiceIT.java index 50e784d..07e9812 100644 --- a/src/test/java/com/neueda/blocking/chassis/service/ChassisServiceTests.java +++ b/src/intTest/java/com/neueda/blocking/chassis/service/ChassisServiceIT.java @@ -1,5 +1,6 @@ package com.neueda.blocking.chassis.service; + import com.neueda.blocking.chassis.entity.ChassisEntity; import com.neueda.blocking.chassis.model.Chassis; import com.neueda.blocking.chassis.repository.ChassisRepository; @@ -18,7 +19,7 @@ import static org.mockito.Mockito.when; @SpringJUnitConfig(ChassisService.class) -class ChassisServiceTests { +class ChassisServiceIT { @MockBean private ChassisRepository chassisRepository; @@ -32,8 +33,8 @@ void testRetrieveAllChassis() { //Given List chassisEntity = List.of( - new ChassisEntity(1L,"name","description 1"), - new ChassisEntity(2L,"name","description 2")); + new ChassisEntity(1L,"name","description 1"), + new ChassisEntity(2L,"name","description 2")); when(chassisRepository.findAll()) .thenReturn(chassisEntity); diff --git a/src/intTest/resources/config/application.yaml b/src/intTest/resources/config/application.yaml new file mode 100644 index 0000000..e9324b2 --- /dev/null +++ b/src/intTest/resources/config/application.yaml @@ -0,0 +1,57 @@ +spring: + main: + banner-mode: off + + h2: + console: + enabled: on + + sql: + init: + mode: never + + liquibase: + enabled: false + change-log: "classpath:/db/changelog/db.changelog-master.xml" + test-rollback-on-update: on + + jpa: + show-sql: true + generate-ddl: true + hibernate: + ddl-auto: create-drop + + codec: + log-request-details: on + +server: + error: + include-exception: on + include-stacktrace: always + +client: + base-url: https://mock.server.com + +springdoc: + api-docs: + enabled: off + +apidoc: + title: Java Blocking Microservice Test + description: Microservice Test for Blocking Restful API with Spring Boot + version: Test + +debug: off +trace: off +logging: + level: + root: error + web: trace + sql: trace + org: + springframework: + jdbc: + datasource: trace + liquibase: + database: trace + diff --git a/src/intTest/resources/db/changelog/db-test.changelog-master.xml b/src/intTest/resources/db/changelog/db-test.changelog-master.xml new file mode 100644 index 0000000..54d01e8 --- /dev/null +++ b/src/intTest/resources/db/changelog/db-test.changelog-master.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/intTest/resources/db/delete_all_chassis_entity.sql b/src/intTest/resources/db/delete_all_chassis_entity.sql new file mode 100644 index 0000000..b3aa53f --- /dev/null +++ b/src/intTest/resources/db/delete_all_chassis_entity.sql @@ -0,0 +1 @@ +DELETE FROM chassis_entity; diff --git a/src/intTest/resources/db/insert_one_chassis_entity.sql b/src/intTest/resources/db/insert_one_chassis_entity.sql new file mode 100644 index 0000000..5fa8479 --- /dev/null +++ b/src/intTest/resources/db/insert_one_chassis_entity.sql @@ -0,0 +1 @@ +INSERT INTO chassis_entity(name, description) VALUES ('integration test', 'description text'); diff --git a/src/main/java/com/neueda/blocking/chassis/client/ClientHelper.java b/src/main/java/com/neueda/blocking/chassis/client/ClientHelper.java index 5f7fdf8..8a905fd 100644 --- a/src/main/java/com/neueda/blocking/chassis/client/ClientHelper.java +++ b/src/main/java/com/neueda/blocking/chassis/client/ClientHelper.java @@ -1,15 +1,9 @@ package com.neueda.blocking.chassis.client; import com.fasterxml.jackson.databind.ObjectMapper; import com.neueda.blocking.chassis.properties.ClientProperties; - - - - import lombok.extern.slf4j.Slf4j; - import org.springframework.web.client.RestClientException; import org.springframework.web.util.UriBuilder; -import static org.springframework.web.util.UriComponentsBuilder.fromUri; import java.io.IOException; import java.net.URI; @@ -17,7 +11,7 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.function.Function; - +import static org.springframework.web.util.UriComponentsBuilder.fromUri; @Slf4j public class ClientHelper { @@ -45,9 +39,10 @@ T performGetRequest(Function uriFunction, Class clazz) { return clazz.isAssignableFrom(String.class) ? (T) response : objectMapper.readValue(response, clazz); } catch (IOException | InterruptedException e) { + log.error("Failed to send GET request", e); throw new RestClientException(e.getMessage(), e); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/neueda/blocking/chassis/entity/ChassisEntity.java b/src/main/java/com/neueda/blocking/chassis/entity/ChassisEntity.java index 337ad03..ec95e1b 100644 --- a/src/main/java/com/neueda/blocking/chassis/entity/ChassisEntity.java +++ b/src/main/java/com/neueda/blocking/chassis/entity/ChassisEntity.java @@ -1,5 +1,4 @@ package com.neueda.blocking.chassis.entity; - import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,7 +9,6 @@ import javax.persistence.GenerationType; import javax.persistence.Id; - @Entity @Getter @Setter @@ -24,5 +22,4 @@ public class ChassisEntity { private String name; private String description; - -} +} \ No newline at end of file diff --git a/src/main/resources/config/application.yaml b/src/main/resources/config/application.yaml index bd9f6eb..44ba5ff 100644 --- a/src/main/resources/config/application.yaml +++ b/src/main/resources/config/application.yaml @@ -2,21 +2,25 @@ spring: main: banner-mode: log config: - import: "configtree:db/" + import: configtree:config/ application: - name: @project.artifactId@ + name: @name@ h2: console: - enabled: on + enabled: off sql: init: mode: never liquibase: - change-log: "classpath:/db/changelog/db.changelog-master.xml" + change-log: db/changelog/db.changelog-master.xml + url: ${db.url.jdbc} + user: ${db.username:sa} + password: ${db.password} + contexts: prod test-rollback-on-update: on datasource: @@ -54,20 +58,20 @@ management: springdoc: use-management-port: on show-actuator: on - api-docs: - enabled: on - path: /api-docs + #api-docs: + #enabled: on + #path: /api-docs apidoc: - title: @project.name@ - description: @project.description@ - version: @project.version@ + title: @name@ + description: @description@ + version: @version@ debug: off trace: off logging: file: - path: /var/log/@build.name@ + name: /var/log/spring-boot/@jarBaseName@.log level: root: error web: trace diff --git a/src/test/java/com/neueda/blocking/chassis/client/GithubClientTests.java b/src/test/java/com/neueda/blocking/chassis/client/GithubClientTests.java index 726908e..fff326f 100644 --- a/src/test/java/com/neueda/blocking/chassis/client/GithubClientTests.java +++ b/src/test/java/com/neueda/blocking/chassis/client/GithubClientTests.java @@ -1,7 +1,6 @@ package com.neueda.blocking.chassis.client; import com.github.tomakehurst.wiremock.WireMockServer; - import com.neueda.blocking.chassis.properties.ClientProperties; import org.junit.jupiter.api.BeforeAll;