diff --git a/README.adoc b/README.adoc index 68c2aa2d..d2407920 100644 --- a/README.adoc +++ b/README.adoc @@ -62,7 +62,6 @@ All tutorials are documented in AsciiDoc format and published as an https://anto |link:modulith[Spring Modulith: Building Modular Monolithic Applications] | Structure Spring Boot applications into well-defined modules with clear boundaries |link:data-mongodb-tc-data-load[Spring Test: Load data with Testcontainers] |Load test data with Testcontainers instead of `BeforeEach` |link:test-execution-listeners[Spring Test: Test Execution Listeners] |Implement custom `TestExecutionListener` to manage data in tests -|link:test-rest-assured[Spring Test: Integration with RestAssured] | Implement Behaviour Driven Development with https://rest-assured.io/[RestAssured] |link:test-slice-tests-rest[Spring Test: Implementing Slice Tests for REST application] | Dive into available options to implement tests with Spring Boot's test components |link:web-rest-client[Spring Web: REST Clients for calling Synchronous API] | Implement REST client to perform synchronous API calls |link:web-thymeleaf-xss[Spring Web: Preventing XSS with Thymeleaf] |Prevent Cross-Site Scripting (XSS) attacks in Spring Boot applications using Spring Security and Thymeleaf diff --git a/batch-rest-repository/README.adoc b/batch-rest-repository/README.adoc index 7ea8ecc9..083d0b8a 100644 --- a/batch-rest-repository/README.adoc +++ b/batch-rest-repository/README.adoc @@ -52,7 +52,7 @@ class UserJobConfiguration { private JsonItemReader reader() throws MalformedURLException { JacksonJsonObjectReader jsonObjectReader = new JacksonJsonObjectReader<>(User.class); - jsonObjectReader.setMapper(new ObjectMapper()); + jsonObjectReader.setMapper(new JsonMapper()); return new JsonItemReaderBuilder() .name("userReader") @@ -80,7 +80,7 @@ class UserJobConfiguration { private JsonItemReader reader() throws MalformedURLException { JacksonJsonObjectReader jsonObjectReader = new JacksonJsonObjectReader<>(User.class); - jsonObjectReader.setMapper(new ObjectMapper()); + jsonObjectReader.setMapper(new JsonMapper()); return new JsonItemReaderBuilder() .name("userReader") diff --git a/batch-rest-repository/build.gradle.kts b/batch-rest-repository/build.gradle.kts index 967f6ee6..97aac3fb 100644 --- a/batch-rest-repository/build.gradle.kts +++ b/batch-rest-repository/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,14 +20,14 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-batch") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - implementation("com.fasterxml.jackson.core:jackson-databind") + implementation("tools.jackson.core:jackson-databind") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") testImplementation("org.springframework.batch:spring-batch-test") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/batch-rest-repository/settings.gradle.kts b/batch-rest-repository/settings.gradle.kts index a0998ea9..8b9005e0 100644 --- a/batch-rest-repository/settings.gradle.kts +++ b/batch-rest-repository/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "batch-rest-repository" \ No newline at end of file +rootProject.name = "batch-rest-repository" + +dependencies { + runtimeOnly("com.fasterxml.jackson.core:jackson-annotations:2.21") +} \ No newline at end of file diff --git a/batch-rest-repository/src/main/java/zin/rashidi/boot/batch/rest/user/UserJobConfiguration.java b/batch-rest-repository/src/main/java/zin/rashidi/boot/batch/rest/user/UserJobConfiguration.java index e5e86bc3..901ac15e 100644 --- a/batch-rest-repository/src/main/java/zin/rashidi/boot/batch/rest/user/UserJobConfiguration.java +++ b/batch-rest-repository/src/main/java/zin/rashidi/boot/batch/rest/user/UserJobConfiguration.java @@ -1,24 +1,23 @@ package zin.rashidi.boot.batch.rest.user; -import java.net.MalformedURLException; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.Step; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.data.MongoItemWriter; -import org.springframework.batch.item.data.builder.MongoItemWriterBuilder; -import org.springframework.batch.item.json.JacksonJsonObjectReader; -import org.springframework.batch.item.json.JsonItemReader; -import org.springframework.batch.item.json.builder.JsonItemReaderBuilder; +import org.springframework.batch.infrastructure.item.data.MongoItemWriter; +import org.springframework.batch.infrastructure.item.data.builder.MongoItemWriterBuilder; +import org.springframework.batch.infrastructure.item.json.JacksonJsonObjectReader; +import org.springframework.batch.infrastructure.item.json.JsonItemReader; +import org.springframework.batch.infrastructure.item.json.builder.JsonItemReaderBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.UrlResource; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.transaction.PlatformTransactionManager; +import tools.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.net.MalformedURLException; /** * @author Rashidi Zin @@ -26,7 +25,7 @@ @Configuration class UserJobConfiguration { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final JsonMapper OBJECT_MAPPER = new JsonMapper(); private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; diff --git a/batch-rest-repository/src/test/java/zin/rashidi/boot/batch/rest/user/UserBatchJobTests.java b/batch-rest-repository/src/test/java/zin/rashidi/boot/batch/rest/user/UserBatchJobTests.java index a54d89e6..34bf61e7 100644 --- a/batch-rest-repository/src/test/java/zin/rashidi/boot/batch/rest/user/UserBatchJobTests.java +++ b/batch-rest-repository/src/test/java/zin/rashidi/boot/batch/rest/user/UserBatchJobTests.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; @@ -17,10 +18,10 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.transaction.PlatformTransactionManager; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; +import org.testcontainers.mysql.MySQLContainer; import javax.sql.DataSource; @@ -42,7 +43,7 @@ class UserBatchJobTests { @Container @ServiceConnection - private final static MySQLContainer MYSQL_CONTAINER = new MySQLContainer<>("mysql:lts") + private final static MySQLContainer MYSQL_CONTAINER = new MySQLContainer("mysql:lts") .withInitScript("org/springframework/batch/core/schema-mysql.sql"); @Container diff --git a/batch-skip-step/build.gradle.kts b/batch-skip-step/build.gradle.kts index 4b03d08c..b8db8caa 100644 --- a/batch-skip-step/build.gradle.kts +++ b/batch-skip-step/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,13 +20,14 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-batch") implementation("org.springframework.boot:spring-boot-starter-data-jdbc") - implementation("com.fasterxml.jackson.core:jackson-databind") + implementation("org.springframework.boot:spring-boot-starter-jackson") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.boot:spring-boot-starter-jackson-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") testImplementation("org.springframework.batch:spring-batch-test") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/batch-skip-step/settings.gradle.kts b/batch-skip-step/settings.gradle.kts index 780c1932..45403b1e 100644 --- a/batch-skip-step/settings.gradle.kts +++ b/batch-skip-step/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "batch-skip-step" \ No newline at end of file +rootProject.name = "batch-skip-step" + +dependencies { + runtimeOnly("com.fasterxml.jackson.core:jackson-annotations:2.21") +} \ No newline at end of file diff --git a/batch-skip-step/src/main/java/zin/rashidi/boot/batch/user/UserJobConfiguration.java b/batch-skip-step/src/main/java/zin/rashidi/boot/batch/user/UserJobConfiguration.java index 1588bf0f..9f770a4a 100644 --- a/batch-skip-step/src/main/java/zin/rashidi/boot/batch/user/UserJobConfiguration.java +++ b/batch-skip-step/src/main/java/zin/rashidi/boot/batch/user/UserJobConfiguration.java @@ -1,17 +1,16 @@ package zin.rashidi.boot.batch.user; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.Step; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.database.JdbcBatchItemWriter; -import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; -import org.springframework.batch.item.json.JacksonJsonObjectReader; -import org.springframework.batch.item.json.JsonItemReader; -import org.springframework.batch.item.json.builder.JsonItemReaderBuilder; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.database.JdbcBatchItemWriter; +import org.springframework.batch.infrastructure.item.database.builder.JdbcBatchItemWriterBuilder; +import org.springframework.batch.infrastructure.item.json.JacksonJsonObjectReader; +import org.springframework.batch.infrastructure.item.json.JsonItemReader; +import org.springframework.batch.infrastructure.item.json.builder.JsonItemReaderBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -25,13 +24,9 @@ @Configuration class UserJobConfiguration { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private JsonItemReader reader() { JacksonJsonObjectReader reader = new JacksonJsonObjectReader<>(UserFile.class); - reader.setMapper(OBJECT_MAPPER); - return new JsonItemReaderBuilder() .jsonObjectReader(reader) .name("userReader") diff --git a/batch-skip-step/src/test/java/zin/rashidi/boot/batch/user/UserBatchJobTests.java b/batch-skip-step/src/test/java/zin/rashidi/boot/batch/user/UserBatchJobTests.java index 54540225..bf0e1d4e 100644 --- a/batch-skip-step/src/test/java/zin/rashidi/boot/batch/user/UserBatchJobTests.java +++ b/batch-skip-step/src/test/java/zin/rashidi/boot/batch/user/UserBatchJobTests.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; @@ -16,9 +17,9 @@ import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.PlatformTransactionManager; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import javax.sql.DataSource; @@ -51,7 +52,7 @@ class UserBatchJobTests { @Container @ServiceConnection - private final static MySQLContainer MYSQL_CONTAINER = new MySQLContainer<>("mysql:lts"); + private final static MySQLContainer MYSQL_CONTAINER = new MySQLContainer("mysql:lts"); @Autowired private JobLauncherTestUtils launcher; @@ -68,7 +69,7 @@ void findAll() { assertThat(execution.getExitStatus()).isEqualTo(COMPLETED); }); - var users = jdbc.query("SELECT * FROM users", (rs, _) -> + var users = jdbc.query("SELECT * FROM users", (rs, i) -> new User(rs.getLong("id"), rs.getString("name"), rs.getString("username")) ); @@ -113,7 +114,6 @@ void truncateUsers() { @TestConfiguration static class BatchTestConfiguration extends DefaultBatchConfiguration { - @Override @Bean protected DataSource getDataSource() { return DataSourceBuilder.create() diff --git a/build.gradle.kts b/build.gradle.kts index 3553feec..d9cef833 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { java - id("org.springframework.boot") version "3.5.7" apply false + id("org.springframework.boot") version "4.0.2" apply false id("io.spring.dependency-management") version "1.1.7" id("org.sonarqube") version "7.2.2.6593" id("jacoco-report-aggregation") diff --git a/cloud-jdbc-env-repo/build.gradle.kts b/cloud-jdbc-env-repo/build.gradle.kts index 1365b130..97eccf29 100644 --- a/cloud-jdbc-env-repo/build.gradle.kts +++ b/cloud-jdbc-env-repo/build.gradle.kts @@ -1,13 +1,13 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } group = "zin.rashidi.boot" version = "0.0.1-SNAPSHOT" -val springCloudVersion = "2025.0.0" +val springCloudVersion = "2025.0.1" java { toolchain { @@ -28,6 +28,7 @@ repositories { dependencies { implementation(platform("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}")) + implementation("org.springframework.boot:spring-boot-resttestclient:4.0.2") implementation("org.springframework.boot:spring-boot-starter-data-jdbc") implementation("org.springframework.cloud:spring-cloud-starter-bootstrap") implementation("org.springframework.cloud:spring-cloud-config-server") @@ -35,8 +36,8 @@ dependencies { annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/cloud-jdbc-env-repo/settings.gradle.kts b/cloud-jdbc-env-repo/settings.gradle.kts index 9a9a4e92..d0b5c264 100644 --- a/cloud-jdbc-env-repo/settings.gradle.kts +++ b/cloud-jdbc-env-repo/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "cloud-jdbc-env-repo" \ No newline at end of file +rootProject.name = "cloud-jdbc-env-repo" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/cloud-jdbc-env-repo/src/main/resources/application.yml b/cloud-jdbc-env-repo/src/main/resources/application.yml index 4a3106ba..e4b57fd8 100644 --- a/cloud-jdbc-env-repo/src/main/resources/application.yml +++ b/cloud-jdbc-env-repo/src/main/resources/application.yml @@ -1,3 +1,9 @@ -app: - greet: - name: Default \ No newline at end of file +app.greet.name: Default +spring: + application.name: demo + cloud.config.server: + bootstrap: true + jdbc: + sql: SELECT `KEY`, `VALUE` from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=? + sql-without-profile: SELECT `KEY`, `VALUE` from PROPERTIES where APPLICATION=? and PROFILE='default' and LABEL=? + profiles.active: jdbc \ No newline at end of file diff --git a/cloud-jdbc-env-repo/src/main/resources/bootstrap.yml b/cloud-jdbc-env-repo/src/main/resources/bootstrap.yml deleted file mode 100644 index ab39b36e..00000000 --- a/cloud-jdbc-env-repo/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,13 +0,0 @@ -spring: - application: - name: demo - cloud: - config: - server: - bootstrap: true - jdbc: - sql: SELECT `KEY`, `VALUE` from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=? - sql-without-profile: SELECT `KEY`, `VALUE` from PROPERTIES where APPLICATION=? and PROFILE='default' and LABEL=? - profiles: - active: jdbc - diff --git a/cloud-jdbc-env-repo/src/test/java/zin/rashidi/boot/cloud/jdbcenvrepo/CloudJdbcEnvRepoApplicationTests.java b/cloud-jdbc-env-repo/src/test/java/zin/rashidi/boot/cloud/jdbcenvrepo/CloudJdbcEnvRepoApplicationTests.java index ba2d8cfa..5f470386 100644 --- a/cloud-jdbc-env-repo/src/test/java/zin/rashidi/boot/cloud/jdbcenvrepo/CloudJdbcEnvRepoApplicationTests.java +++ b/cloud-jdbc-env-repo/src/test/java/zin/rashidi/boot/cloud/jdbcenvrepo/CloudJdbcEnvRepoApplicationTests.java @@ -3,21 +3,23 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.testcontainers.containers.MySQLContainer; +import org.springframework.boot.resttestclient.TestRestTemplate; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +@AutoConfigureTestRestTemplate @Testcontainers @SpringBootTest(properties = "spring.datasource.url=jdbc:tc:mysql:lts:///test?TC_INITSCRIPT=init-script.sql", webEnvironment = RANDOM_PORT) class CloudJdbcEnvRepoApplicationTests { @Container - private static final MySQLContainer MYSQL = new MySQLContainer<>("mysql:lts"); + private static final MySQLContainer MYSQL = new MySQLContainer("mysql:lts"); @Autowired private TestRestTemplate restClient; diff --git a/data-domain-events/build.gradle.kts b/data-domain-events/build.gradle.kts index 86a71724..5d498e08 100644 --- a/data-domain-events/build.gradle.kts +++ b/data-domain-events/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -18,13 +18,14 @@ repositories { } dependencies { + implementation("org.springframework.boot:spring-boot-resttestclient:4.0.2") implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-webmvc") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/data-domain-events/settings.gradle.kts b/data-domain-events/settings.gradle.kts index 7f2d8569..48d36db3 100644 --- a/data-domain-events/settings.gradle.kts +++ b/data-domain-events/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-domain-events" \ No newline at end of file +rootProject.name = "data-domain-events" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-domain-events/src/test/java/zin/rashidi/boot/data/de/TestDataDomainEventsApplication.java b/data-domain-events/src/test/java/zin/rashidi/boot/data/de/TestDataDomainEventsApplication.java index e2ab7bbf..69ce8800 100644 --- a/data-domain-events/src/test/java/zin/rashidi/boot/data/de/TestDataDomainEventsApplication.java +++ b/data-domain-events/src/test/java/zin/rashidi/boot/data/de/TestDataDomainEventsApplication.java @@ -4,15 +4,15 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.mysql.MySQLContainer; @TestConfiguration(proxyBeanMethods = false) public class TestDataDomainEventsApplication { @Bean @ServiceConnection - MySQLContainer mysqlContainer() { - return new MySQLContainer<>("mysql:lts"); + MySQLContainer mysqlContainer() { + return new MySQLContainer("mysql:lts"); } public static void main(String[] args) { diff --git a/data-domain-events/src/test/java/zin/rashidi/boot/data/de/availability/BookPurchaseTests.java b/data-domain-events/src/test/java/zin/rashidi/boot/data/de/availability/BookPurchaseTests.java index cee9c59f..5206c061 100644 --- a/data-domain-events/src/test/java/zin/rashidi/boot/data/de/availability/BookPurchaseTests.java +++ b/data-domain-events/src/test/java/zin/rashidi/boot/data/de/availability/BookPurchaseTests.java @@ -7,8 +7,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.resttestclient.TestRestTemplate; import zin.rashidi.boot.data.de.TestDataDomainEventsApplication; import zin.rashidi.boot.data.de.book.Book; @@ -17,6 +18,7 @@ /** * @author Rashidi Zin */ +@AutoConfigureTestRestTemplate @SpringBootTest( classes = TestDataDomainEventsApplication.class, properties = "spring.jpa.hibernate.ddl-auto=create", diff --git a/data-envers-audit/build.gradle.kts b/data-envers-audit/build.gradle.kts index a67ef353..1ac3ef40 100644 --- a/data-envers-audit/build.gradle.kts +++ b/data-envers-audit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -23,8 +23,8 @@ dependencies { runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/data-envers-audit/settings.gradle.kts b/data-envers-audit/settings.gradle.kts index 4cec2a08..48b37814 100644 --- a/data-envers-audit/settings.gradle.kts +++ b/data-envers-audit/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-envers-audit" \ No newline at end of file +rootProject.name = "data-envers-audit" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-envers-audit/src/test/java/zin/rashidi/boot/data/envers/BookAuditRevisionTests.java b/data-envers-audit/src/test/java/zin/rashidi/boot/data/envers/BookAuditRevisionTests.java index 0d9249cd..0bb7e417 100644 --- a/data-envers-audit/src/test/java/zin/rashidi/boot/data/envers/BookAuditRevisionTests.java +++ b/data-envers-audit/src/test/java/zin/rashidi/boot/data/envers/BookAuditRevisionTests.java @@ -12,10 +12,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.data.history.Revision; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; - +import org.testcontainers.mysql.MySQLContainer; import zin.rashidi.boot.data.envers.book.Book; import zin.rashidi.boot.data.envers.book.BookRepository; @@ -28,7 +27,7 @@ class BookAuditRevisionTests { @Container @ServiceConnection - private static final MySQLContainer MYSQL = new MySQLContainer<>("mysql:lts"); + private static final MySQLContainer MYSQL = new MySQLContainer("mysql:lts"); @Autowired private BookRepository repository; diff --git a/data-jdbc-audit/build.gradle.kts b/data-jdbc-audit/build.gradle.kts index d99dfabb..a9455457 100644 --- a/data-jdbc-audit/build.gradle.kts +++ b/data-jdbc-audit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -22,8 +22,8 @@ dependencies { runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-jdbc-audit/settings.gradle.kts b/data-jdbc-audit/settings.gradle.kts index 8f46a497..58acef14 100644 --- a/data-jdbc-audit/settings.gradle.kts +++ b/data-jdbc-audit/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-jdbc-audit" \ No newline at end of file +rootProject.name = "data-jdbc-audit" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/TestcontainersConfiguration.java b/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/TestcontainersConfiguration.java index 6f705f7f..7b2c81a3 100644 --- a/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/TestcontainersConfiguration.java +++ b/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/user/UserAuditTests.java b/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/user/UserAuditTests.java index 58924736..341ee990 100644 --- a/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/user/UserAuditTests.java +++ b/data-jdbc-audit/src/test/java/zin/rashidi/boot/data/jdbc/user/UserAuditTests.java @@ -9,9 +9,9 @@ import org.springframework.data.jdbc.repository.config.EnableJdbcAuditing; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.util.ReflectionTestUtils; -import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; import java.time.Instant; @@ -32,7 +32,7 @@ class UserAuditTests { @Container @ServiceConnection - private static final PostgreSQLContainer postgres = new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + private static final PostgreSQLContainer postgres = new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); @Autowired private UserRepository repository; diff --git a/data-jdbc-schema-generation/build.gradle.kts b/data-jdbc-schema-generation/build.gradle.kts index 9f2c6af0..80f98f95 100644 --- a/data-jdbc-schema-generation/build.gradle.kts +++ b/data-jdbc-schema-generation/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,12 +19,12 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jdbc") - implementation("org.liquibase:liquibase-core") + implementation("org.springframework.boot:spring-boot-starter-liquibase") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-jdbc-schema-generation/settings.gradle.kts b/data-jdbc-schema-generation/settings.gradle.kts index af54464e..32db9497 100644 --- a/data-jdbc-schema-generation/settings.gradle.kts +++ b/data-jdbc-schema-generation/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-jdbc-schema-generation" \ No newline at end of file +rootProject.name = "data-jdbc-schema-generation" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-jdbc-schema-generation/src/test/java/zin/rashidi/boot/jdbcscgm/TestcontainersConfiguration.java b/data-jdbc-schema-generation/src/test/java/zin/rashidi/boot/jdbcscgm/TestcontainersConfiguration.java index 4a4c29e8..8b9b6ebd 100644 --- a/data-jdbc-schema-generation/src/test/java/zin/rashidi/boot/jdbcscgm/TestcontainersConfiguration.java +++ b/data-jdbc-schema-generation/src/test/java/zin/rashidi/boot/jdbcscgm/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-jpa-audit/build.gradle.kts b/data-jpa-audit/build.gradle.kts index 65c861c6..0f7a5c01 100644 --- a/data-jpa-audit/build.gradle.kts +++ b/data-jpa-audit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,11 +19,12 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-data-jpa-test:4.0.2") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/data-jpa-audit/src/test/java/zin/rashidi/boot/data/user/UserAuditTests.java b/data-jpa-audit/src/test/java/zin/rashidi/boot/data/user/UserAuditTests.java index b1244e8b..5a2e2b7d 100644 --- a/data-jpa-audit/src/test/java/zin/rashidi/boot/data/user/UserAuditTests.java +++ b/data-jpa-audit/src/test/java/zin/rashidi/boot/data/user/UserAuditTests.java @@ -3,15 +3,15 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.util.ReflectionTestUtils; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import java.time.Instant; @@ -26,7 +26,7 @@ class UserAuditTests { @Container @ServiceConnection - private final static MySQLContainer MYSQL = new MySQLContainer<>("mysql:lts"); + private final static MySQLContainer MYSQL = new MySQLContainer("mysql:lts"); @Autowired private UserRepository repository; diff --git a/data-jpa-event/build.gradle.kts b/data-jpa-event/build.gradle.kts index 7bdc163b..5d7de911 100644 --- a/data-jpa-event/build.gradle.kts +++ b/data-jpa-event/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,10 +20,10 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") runtimeOnly("org.postgresql:postgresql") - testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-jpa-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-jpa-event/src/test/java/zin/rashidi/data/event/TestcontainersConfiguration.java b/data-jpa-event/src/test/java/zin/rashidi/data/event/TestcontainersConfiguration.java index c83abe78..fbd5fc2c 100644 --- a/data-jpa-event/src/test/java/zin/rashidi/data/event/TestcontainersConfiguration.java +++ b/data-jpa-event/src/test/java/zin/rashidi/data/event/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-jpa-event/src/test/java/zin/rashidi/data/event/user/UserRepositoryTests.java b/data-jpa-event/src/test/java/zin/rashidi/data/event/user/UserRepositoryTests.java index 268c7242..9c0c4545 100644 --- a/data-jpa-event/src/test/java/zin/rashidi/data/event/user/UserRepositoryTests.java +++ b/data-jpa-event/src/test/java/zin/rashidi/data/event/user/UserRepositoryTests.java @@ -3,13 +3,13 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; +import org.springframework.boot.jpa.test.autoconfigure.TestEntityManager; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.ComponentScan.Filter; -import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -24,7 +24,7 @@ class UserRepositoryTests { @Container @ServiceConnection - private static final PostgreSQLContainer postgresql = new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + private static final PostgreSQLContainer postgresql = new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); @Autowired private TestEntityManager em; diff --git a/data-jpa-filtered-query/build.gradle.kts b/data-jpa-filtered-query/build.gradle.kts index 65c861c6..0f7a5c01 100644 --- a/data-jpa-filtered-query/build.gradle.kts +++ b/data-jpa-filtered-query/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,11 +19,12 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-data-jpa-test:4.0.2") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/data-jpa-filtered-query/src/main/java/zin/rashidi/boot/data/jpa/jpa/JpaCustomBaseRepository.java b/data-jpa-filtered-query/src/main/java/zin/rashidi/boot/data/jpa/jpa/JpaCustomBaseRepository.java index 1d776d0f..fb23c456 100644 --- a/data-jpa-filtered-query/src/main/java/zin/rashidi/boot/data/jpa/jpa/JpaCustomBaseRepository.java +++ b/data-jpa-filtered-query/src/main/java/zin/rashidi/boot/data/jpa/jpa/JpaCustomBaseRepository.java @@ -23,7 +23,7 @@ public JpaCustomBaseRepository(JpaEntityInformation entityInformation, Ent @Override public List findAll() { var hasStatusField = Stream.of(ReflectionUtils.getDeclaredMethods(getDomainClass())).anyMatch(field -> field.getName().equals("status")); - return hasStatusField ? findAll((root, _, _) -> root.get("status").in(ACTIVE)) : super.findAll(); + return hasStatusField ? findAll((root, query, builder) -> root.get("status").in(ACTIVE)) : super.findAll(); } } diff --git a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/TestDataJpaFilteredQueryApplication.java b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/TestDataJpaFilteredQueryApplication.java index fb58524f..7ad7f51f 100644 --- a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/TestDataJpaFilteredQueryApplication.java +++ b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/TestDataJpaFilteredQueryApplication.java @@ -4,7 +4,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.mysql.MySQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -12,8 +12,8 @@ public class TestDataJpaFilteredQueryApplication { @Bean @ServiceConnection - MySQLContainer mysqlContainer() { - return new MySQLContainer<>(DockerImageName.parse("mysql:lts")); + MySQLContainer mysqlContainer() { + return new MySQLContainer(DockerImageName.parse("mysql:lts")); } public static void main(String[] args) { diff --git a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/country/CountryRepositoryTests.java b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/country/CountryRepositoryTests.java index 4b122294..9b5b4c5a 100644 --- a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/country/CountryRepositoryTests.java +++ b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/country/CountryRepositoryTests.java @@ -4,13 +4,13 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import java.util.List; @@ -29,7 +29,7 @@ class CountryRepositoryTests { @Container @ServiceConnection - private static final MySQLContainer mysql = new MySQLContainer<>("mysql:lts"); + private static final MySQLContainer mysql = new MySQLContainer("mysql:lts"); @Autowired private CountryRepository countries; diff --git a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/user/UserRepositoryTests.java b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/user/UserRepositoryTests.java index e92210b6..26315ad9 100644 --- a/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/user/UserRepositoryTests.java +++ b/data-jpa-filtered-query/src/test/java/zin/rashidi/boot/data/jpa/user/UserRepositoryTests.java @@ -4,13 +4,13 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import java.util.List; @@ -31,7 +31,7 @@ class UserRepositoryTests { @Container @ServiceConnection - private static final MySQLContainer mysql = new MySQLContainer<>("mysql:lts"); + private static final MySQLContainer mysql = new MySQLContainer("mysql:lts"); @Autowired private UserRepository users; diff --git a/data-jpa-hibernate-cache/build.gradle.kts b/data-jpa-hibernate-cache/build.gradle.kts index 80c66512..89684e72 100644 --- a/data-jpa-hibernate-cache/build.gradle.kts +++ b/data-jpa-hibernate-cache/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -18,14 +18,15 @@ repositories { } dependencies { - implementation("org.ehcache:ehcache::jakarta") + implementation("org.ehcache:ehcache:3.10.9:jakarta") implementation("org.hibernate.orm:hibernate-jcache") implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-data-jpa-test:4.0.2") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-jpa-hibernate-cache/settings.gradle.kts b/data-jpa-hibernate-cache/settings.gradle.kts index bd5512b8..3d45b8b8 100644 --- a/data-jpa-hibernate-cache/settings.gradle.kts +++ b/data-jpa-hibernate-cache/settings.gradle.kts @@ -1 +1,5 @@ rootProject.name = "data-jpa-hibernate-cache" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} diff --git a/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/TestcontainersConfiguration.java b/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/TestcontainersConfiguration.java index bedc6fa6..3a3d0532 100644 --- a/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/TestcontainersConfiguration.java +++ b/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/customer/CustomerRepositoryTests.java b/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/customer/CustomerRepositoryTests.java index 82090a63..8f456daa 100644 --- a/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/customer/CustomerRepositoryTests.java +++ b/data-jpa-hibernate-cache/src/test/java/zin/rashidi/datajpa/hibernatecache/customer/CustomerRepositoryTests.java @@ -6,7 +6,7 @@ import org.junit.jupiter.api.*; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; diff --git a/data-mongodb-audit/build.gradle.kts b/data-mongodb-audit/build.gradle.kts index 0a0874b9..a37e4e0a 100644 --- a/data-mongodb-audit/build.gradle.kts +++ b/data-mongodb-audit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,10 +19,11 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-mongodb-test") + testImplementation("org.springframework.boot:spring-boot-starter-mongodb-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") } tasks.named("test") { diff --git a/data-mongodb-audit/settings.gradle.kts b/data-mongodb-audit/settings.gradle.kts index fa4e078a..2db73755 100644 --- a/data-mongodb-audit/settings.gradle.kts +++ b/data-mongodb-audit/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-mongodb-audit" \ No newline at end of file +rootProject.name = "data-mongodb-audit" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-mongodb-audit/src/test/java/zin/rashidi/boot/data/mongodb/user/UserAuditTests.java b/data-mongodb-audit/src/test/java/zin/rashidi/boot/data/mongodb/user/UserAuditTests.java index 5469b91d..f9556283 100644 --- a/data-mongodb-audit/src/test/java/zin/rashidi/boot/data/mongodb/user/UserAuditTests.java +++ b/data-mongodb-audit/src/test/java/zin/rashidi/boot/data/mongodb/user/UserAuditTests.java @@ -12,9 +12,9 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.data.mongodb.config.EnableMongoAuditing; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; /** * @author Rashidi Zin diff --git a/data-mongodb-full-text-search/build.gradle.kts b/data-mongodb-full-text-search/build.gradle.kts index 0a0874b9..a37e4e0a 100644 --- a/data-mongodb-full-text-search/build.gradle.kts +++ b/data-mongodb-full-text-search/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,10 +19,11 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-mongodb-test") + testImplementation("org.springframework.boot:spring-boot-starter-mongodb-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") } tasks.named("test") { diff --git a/data-mongodb-full-text-search/settings.gradle.kts b/data-mongodb-full-text-search/settings.gradle.kts index 34df9676..44318ec6 100644 --- a/data-mongodb-full-text-search/settings.gradle.kts +++ b/data-mongodb-full-text-search/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-mongodb-full-text-search" \ No newline at end of file +rootProject.name = "data-mongodb-full-text-search" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-mongodb-full-text-search/src/test/java/zin/rashidi/boot/data/mongodb/character/CharacterRepositoryTests.java b/data-mongodb-full-text-search/src/test/java/zin/rashidi/boot/data/mongodb/character/CharacterRepositoryTests.java index 9ce38f34..fe478173 100644 --- a/data-mongodb-full-text-search/src/test/java/zin/rashidi/boot/data/mongodb/character/CharacterRepositoryTests.java +++ b/data-mongodb-full-text-search/src/test/java/zin/rashidi/boot/data/mongodb/character/CharacterRepositoryTests.java @@ -15,9 +15,9 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.index.TextIndexDefinition; import org.springframework.data.mongodb.core.query.TextCriteria; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; /** * @author Rashidi Zin diff --git a/data-mongodb-tc-data-load/build.gradle.kts b/data-mongodb-tc-data-load/build.gradle.kts index 3b9aa08a..68ede0b5 100644 --- a/data-mongodb-tc-data-load/build.gradle.kts +++ b/data-mongodb-tc-data-load/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,11 +19,12 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.boot:spring-boot-starter-data-mongodb-test") + testImplementation("org.springframework.boot:spring-boot-starter-mongodb-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") - testImplementation("com.fasterxml.jackson.core:jackson-databind") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") + testImplementation("tools.jackson.core:jackson-databind") } tasks.named("test") { diff --git a/data-mongodb-tc-data-load/settings.gradle.kts b/data-mongodb-tc-data-load/settings.gradle.kts index 7e587d08..07565953 100644 --- a/data-mongodb-tc-data-load/settings.gradle.kts +++ b/data-mongodb-tc-data-load/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-mongodb-tc-data-load" \ No newline at end of file +rootProject.name = "data-mongodb-tc-data-load" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-mongodb-tc-data-load/src/test/java/zin/rashidi/data/mongodb/tc/dataload/user/UserRepositoryTests.java b/data-mongodb-tc-data-load/src/test/java/zin/rashidi/data/mongodb/tc/dataload/user/UserRepositoryTests.java index c1a647d7..dc4a2c5b 100644 --- a/data-mongodb-tc-data-load/src/test/java/zin/rashidi/data/mongodb/tc/dataload/user/UserRepositoryTests.java +++ b/data-mongodb-tc-data-load/src/test/java/zin/rashidi/data/mongodb/tc/dataload/user/UserRepositoryTests.java @@ -11,9 +11,9 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.context.annotation.FilterType.ASSIGNABLE_TYPE; diff --git a/data-mongodb-transactional/build.gradle.kts b/data-mongodb-transactional/build.gradle.kts index 1a614a13..82283097 100644 --- a/data-mongodb-transactional/build.gradle.kts +++ b/data-mongodb-transactional/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -18,12 +18,14 @@ repositories { } dependencies { + implementation("org.springframework.boot:spring-boot-resttestclient:4.0.2") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - implementation("org.springframework.boot:spring-boot-starter-web") - testImplementation("org.springframework.boot:spring-boot-starter-test") + implementation("org.springframework.boot:spring-boot-starter-webmvc") + testImplementation("org.springframework.boot:spring-boot-starter-data-mongodb-test") + testImplementation("org.springframework.boot:spring-boot-starter-mongodb-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") } tasks.named("test") { diff --git a/data-mongodb-transactional/settings.gradle.kts b/data-mongodb-transactional/settings.gradle.kts index dd29759e..3570a92d 100644 --- a/data-mongodb-transactional/settings.gradle.kts +++ b/data-mongodb-transactional/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-mongodb-transactional" \ No newline at end of file +rootProject.name = "data-mongodb-transactional" + +dependencies { + runtimeOnly("org.springframework:spring-webmvc:7.0.3") +} \ No newline at end of file diff --git a/data-mongodb-transactional/src/test/java/zin/rashidi/boot/data/mongodb/tm/user/CreateUserTests.java b/data-mongodb-transactional/src/test/java/zin/rashidi/boot/data/mongodb/tm/user/CreateUserTests.java index 588f0d3e..94747392 100644 --- a/data-mongodb-transactional/src/test/java/zin/rashidi/boot/data/mongodb/tm/user/CreateUserTests.java +++ b/data-mongodb-transactional/src/test/java/zin/rashidi/boot/data/mongodb/tm/user/CreateUserTests.java @@ -2,14 +2,15 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.resttestclient.TestRestTemplate; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -20,6 +21,7 @@ /** * @author Rashidi Zin */ +@AutoConfigureTestRestTemplate @SpringBootTest(webEnvironment = RANDOM_PORT) @Testcontainers class CreateUserTests { diff --git a/data-redis-cache/build.gradle.kts b/data-redis-cache/build.gradle.kts index 7cded78d..675b518e 100644 --- a/data-redis-cache/build.gradle.kts +++ b/data-redis-cache/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,12 +19,13 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-data-jpa-test:4.0.2") implementation("org.springframework.boot:spring-boot-starter-data-redis") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testImplementation("com.redis:testcontainers-redis") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-redis-cache/settings.gradle.kts b/data-redis-cache/settings.gradle.kts index 2fbd83c1..67eb8a42 100644 --- a/data-redis-cache/settings.gradle.kts +++ b/data-redis-cache/settings.gradle.kts @@ -1 +1,5 @@ rootProject.name = "data-redis-cache" + +dependencies { + runtimeOnly("org.springframework:spring-jdbc:7.0.3") +} diff --git a/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/TestcontainersConfiguration.java b/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/TestcontainersConfiguration.java index 9c5bfa07..a6096101 100644 --- a/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/TestcontainersConfiguration.java +++ b/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/TestcontainersConfiguration.java @@ -4,7 +4,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -12,8 +12,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } @Bean diff --git a/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/customer/CustomerRepositoryTests.java b/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/customer/CustomerRepositoryTests.java index 2d971d2e..5c8a51f6 100644 --- a/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/customer/CustomerRepositoryTests.java +++ b/data-redis-cache/src/test/java/zin/rashidi/dataredis/cache/customer/CustomerRepositoryTests.java @@ -4,9 +4,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; +import org.springframework.boot.cache.autoconfigure.CacheAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.ComponentScan.Filter; diff --git a/data-repository-definition/build.gradle.kts b/data-repository-definition/build.gradle.kts index da037a33..da309d71 100644 --- a/data-repository-definition/build.gradle.kts +++ b/data-repository-definition/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -22,8 +22,8 @@ dependencies { runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-repository-definition/settings.gradle.kts b/data-repository-definition/settings.gradle.kts index 54c30275..35cf9f2f 100644 --- a/data-repository-definition/settings.gradle.kts +++ b/data-repository-definition/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-repository-definition" \ No newline at end of file +rootProject.name = "data-repository-definition" + +dependencies { + runtimeOnly("org.springframework:spring-context:7.0.3") +} \ No newline at end of file diff --git a/data-repository-definition/src/test/java/zin/rashidi/data/repositorydefinition/TestcontainersConfiguration.java b/data-repository-definition/src/test/java/zin/rashidi/data/repositorydefinition/TestcontainersConfiguration.java index 53dc6aa5..07d88da0 100644 --- a/data-repository-definition/src/test/java/zin/rashidi/data/repositorydefinition/TestcontainersConfiguration.java +++ b/data-repository-definition/src/test/java/zin/rashidi/data/repositorydefinition/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-rest-composite-id/build.gradle.kts b/data-rest-composite-id/build.gradle.kts index 344efc23..6358334b 100644 --- a/data-rest-composite-id/build.gradle.kts +++ b/data-rest-composite-id/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,11 +20,12 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-rest") + implementation("org.springframework.boot:spring-boot-starter-webmvc-test:4.0.2") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/data-rest-composite-id/settings.gradle.kts b/data-rest-composite-id/settings.gradle.kts index 7da8964b..0c4aa877 100644 --- a/data-rest-composite-id/settings.gradle.kts +++ b/data-rest-composite-id/settings.gradle.kts @@ -1 +1,5 @@ rootProject.name = "data-rest-composite-id" + +dependencies { + runtimeOnly("org.springframework:spring-jdbc:7.0.3") +} diff --git a/data-rest-composite-id/src/main/java/zin/rashidi/datarest/compositeid/book/Author.java b/data-rest-composite-id/src/main/java/zin/rashidi/datarest/compositeid/book/Author.java index ba75e7d8..c1836b03 100644 --- a/data-rest-composite-id/src/main/java/zin/rashidi/datarest/compositeid/book/Author.java +++ b/data-rest-composite-id/src/main/java/zin/rashidi/datarest/compositeid/book/Author.java @@ -19,7 +19,6 @@ class Author { @Embeddable static class Id implements Serializable { - @GeneratedValue private Long id; public Long id() { diff --git a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/TestcontainersConfiguration.java b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/TestcontainersConfiguration.java index 8de66d22..687287cf 100644 --- a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/TestcontainersConfiguration.java +++ b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateAuthorTests.java b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateAuthorTests.java index ab75b0e2..43a10ec6 100644 --- a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateAuthorTests.java +++ b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateAuthorTests.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.web.servlet.assertj.MockMvcTester; diff --git a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateBookTests.java b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateBookTests.java index bf9a2637..c601a875 100644 --- a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateBookTests.java +++ b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/CreateBookTests.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.jdbc.Sql; diff --git a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/GetBookTests.java b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/GetBookTests.java index da81f84d..b20e6733 100644 --- a/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/GetBookTests.java +++ b/data-rest-composite-id/src/test/java/zin/rashidi/datarest/compositeid/book/GetBookTests.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.jdbc.Sql; diff --git a/data-rest-validation/build.gradle.kts b/data-rest-validation/build.gradle.kts index 429c4cc9..f91c5655 100644 --- a/data-rest-validation/build.gradle.kts +++ b/data-rest-validation/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -18,15 +18,16 @@ repositories { } dependencies { + implementation("org.springframework.boot:spring-boot-resttestclient:4.0.2") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") implementation("org.springframework.boot:spring-boot-starter-data-rest") runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") + testImplementation("org.testcontainers:testcontainers-mysql") } tasks.named("test") { diff --git a/data-rest-validation/settings.gradle.kts b/data-rest-validation/settings.gradle.kts index 9c16ad3d..6594e5f3 100644 --- a/data-rest-validation/settings.gradle.kts +++ b/data-rest-validation/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "data-rest-validation" \ No newline at end of file +rootProject.name = "data-rest-validation" + +dependencies { + runtimeOnly("org.springframework:spring-jdbc:7.0.3") +} \ No newline at end of file diff --git a/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/TestDataRestValidationApplication.java b/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/TestDataRestValidationApplication.java index d64dbe7e..ad063386 100644 --- a/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/TestDataRestValidationApplication.java +++ b/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/TestDataRestValidationApplication.java @@ -4,8 +4,8 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.mongodb.MongoDBContainer; +import org.testcontainers.mysql.MySQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -19,8 +19,8 @@ MongoDBContainer mongoDbContainer() { @Bean @ServiceConnection - MySQLContainer mysqlContainer() { - return new MySQLContainer<>(DockerImageName.parse("mysql:lts")); + MySQLContainer mysqlContainer() { + return new MySQLContainer(DockerImageName.parse("mysql:lts")); } public static void main(String[] args) { diff --git a/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/book/CreateBookTests.java b/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/book/CreateBookTests.java index 2bc17a61..f8dfea3d 100644 --- a/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/book/CreateBookTests.java +++ b/data-rest-validation/src/test/java/zin/rashidi/boot/data/rest/book/CreateBookTests.java @@ -13,8 +13,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.resttestclient.TestRestTemplate; import org.springframework.context.annotation.Import; import org.springframework.data.rest.webmvc.support.RepositoryConstraintViolationExceptionMessage.ValidationError; import org.springframework.http.HttpEntity; @@ -25,6 +26,7 @@ /** * @author Rashidi Zin */ +@AutoConfigureTestRestTemplate @Import(TestDataRestValidationApplication.class) @SpringBootTest(webEnvironment = RANDOM_PORT, properties = "spring.jpa.hibernate.ddl-auto=create-drop") class CreateBookTests { diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 715a35e6..d8e6fa14 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -29,7 +29,6 @@ * Spring Test ** xref:data-mongodb-tc-data-load.adoc[Load data with Testcontainers] ** xref:test-execution-listeners.adoc[Test Execution Listeners] -** xref:test-rest-assured.adoc[Integration with RestAssured] ** xref:test-slice-tests-rest.adoc[Implementing Slice Tests for REST application] * Spring Web ** xref:web-rest-client.adoc[REST Clients for calling Synchronous API] diff --git a/graphql/build.gradle.kts b/graphql/build.gradle.kts index d41f2071..59879565 100644 --- a/graphql/build.gradle.kts +++ b/graphql/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,7 +20,7 @@ repositories { dependencies { implementation("com.graphql-java:graphql-java-extended-scalars:24.0") implementation("org.springframework.boot:spring-boot-starter-graphql") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-webmvc") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework:spring-webflux") testImplementation("org.springframework.graphql:spring-graphql-test") diff --git a/graphql/settings.gradle.kts b/graphql/settings.gradle.kts index 502189ab..1fb3d372 100644 --- a/graphql/settings.gradle.kts +++ b/graphql/settings.gradle.kts @@ -1 +1,5 @@ -rootProject.name = "graphql" \ No newline at end of file +rootProject.name = "graphql" + +dependencies { + runtimeOnly("org.springframework:spring-webmvc:7.0.3") +} \ No newline at end of file diff --git a/jooq/build.gradle.kts b/jooq/build.gradle.kts index 2ae28a05..539654c4 100644 --- a/jooq/build.gradle.kts +++ b/jooq/build.gradle.kts @@ -3,7 +3,7 @@ import org.jooq.meta.kotlin.* plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" id("nu.studer.jooq") version "10.2" } @@ -28,8 +28,8 @@ dependencies { runtimeOnly("com.mysql:mysql-connector-j") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mysql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mysql") } dependencyManagement { diff --git a/jooq/settings.gradle b/jooq/settings.gradle index 12e7c919..84fbde0f 100644 --- a/jooq/settings.gradle +++ b/jooq/settings.gradle @@ -1 +1,5 @@ rootProject.name = 'jooq' + +dependencies { + runtimeOnly "org.springframework:spring-context:7.0.3" +} diff --git a/jooq/src/test/java/zin/rashidi/boot/jooq/TestJooqApplication.java b/jooq/src/test/java/zin/rashidi/boot/jooq/TestJooqApplication.java index 7fed606d..7fce3bb8 100644 --- a/jooq/src/test/java/zin/rashidi/boot/jooq/TestJooqApplication.java +++ b/jooq/src/test/java/zin/rashidi/boot/jooq/TestJooqApplication.java @@ -4,7 +4,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.mysql.MySQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -16,8 +16,8 @@ public static void main(String[] args) { @Bean @ServiceConnection - MySQLContainer mysqlContainer() { - return new MySQLContainer<>(DockerImageName.parse("mysql:lts")); + MySQLContainer mysqlContainer() { + return new MySQLContainer(DockerImageName.parse("mysql:lts")); } } diff --git a/jooq/src/test/java/zin/rashidi/boot/jooq/user/UserRepositoryTests.java b/jooq/src/test/java/zin/rashidi/boot/jooq/user/UserRepositoryTests.java index 3bd5e91a..41135db2 100644 --- a/jooq/src/test/java/zin/rashidi/boot/jooq/user/UserRepositoryTests.java +++ b/jooq/src/test/java/zin/rashidi/boot/jooq/user/UserRepositoryTests.java @@ -8,9 +8,9 @@ import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.stereotype.Repository; import org.springframework.test.context.jdbc.Sql; -import org.testcontainers.containers.MySQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mysql.MySQLContainer; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +24,7 @@ class UserRepositoryTests { @Container @ServiceConnection - private static final MySQLContainer container = new MySQLContainer<>("mysql:lts"); + private static final MySQLContainer container = new MySQLContainer("mysql:lts"); @Autowired private UserRepository repository; diff --git a/modulith/build.gradle.kts b/modulith/build.gradle.kts index e3be53c8..eb8990e6 100644 --- a/modulith/build.gradle.kts +++ b/modulith/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -27,8 +27,8 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") testImplementation("org.springframework.modulith:spring-modulith-starter-test") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/modulith/src/test/java/zin/rashidi/boot/modulith/TestcontainersConfiguration.java b/modulith/src/test/java/zin/rashidi/boot/modulith/TestcontainersConfiguration.java index 87c21c0c..059ed31a 100644 --- a/modulith/src/test/java/zin/rashidi/boot/modulith/TestcontainersConfiguration.java +++ b/modulith/src/test/java/zin/rashidi/boot/modulith/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")) + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")) .withInitScripts("schema.sql", "schema-data.sql"); } diff --git a/settings.gradle.kts b/settings.gradle.kts index cbfc3def..77680dff 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,7 +23,6 @@ include("graphql") include("jooq") include("modulith") include("test-execution-listeners") -include("test-rest-assured") include("test-slice-tests-rest") include("web-rest-client") include("web-thymeleaf-xss") \ No newline at end of file diff --git a/test-execution-listeners/build.gradle.kts b/test-execution-listeners/build.gradle.kts index 0a0874b9..e913574d 100644 --- a/test-execution-listeners/build.gradle.kts +++ b/test-execution-listeners/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -21,8 +21,8 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-mongodb") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-mongodb") } tasks.named("test") { diff --git a/test-execution-listeners/settings.gradle b/test-execution-listeners/settings.gradle index c653f0de..d6529c67 100644 --- a/test-execution-listeners/settings.gradle +++ b/test-execution-listeners/settings.gradle @@ -1 +1,5 @@ rootProject.name = 'test-execution-listeners' + +dependencies { + runtimeOnly "org.springframework:spring-context:7.0.3" +} diff --git a/test-execution-listeners/src/test/java/zin/rashidi/boot/test/user/UserRepositoryTests.java b/test-execution-listeners/src/test/java/zin/rashidi/boot/test/user/UserRepositoryTests.java index 0a96596d..ed9be349 100644 --- a/test-execution-listeners/src/test/java/zin/rashidi/boot/test/user/UserRepositoryTests.java +++ b/test-execution-listeners/src/test/java/zin/rashidi/boot/test/user/UserRepositoryTests.java @@ -10,9 +10,9 @@ import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.test.context.TestExecutionListeners; -import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.mongodb.MongoDBContainer; /** * @author Rashidi Zin diff --git a/test-rest-assured/.gitignore b/test-rest-assured/.gitignore deleted file mode 100644 index c2065bc2..00000000 --- a/test-rest-assured/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -HELP.md -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ diff --git a/test-rest-assured/README.adoc b/test-rest-assured/README.adoc deleted file mode 100644 index 4b86be3b..00000000 --- a/test-rest-assured/README.adoc +++ /dev/null @@ -1,431 +0,0 @@ -= Spring Test: Implement BDD with RestAssured -:source-highlighter: highlight.js -Rashidi Zin -1.1, November 16, 2024: Fix broken build -:toc: -:nofooter: -:icons: font -:url-quickref: https://github.com/rashidi/spring-boot-tutorials/tree/master/test-rest-assured - -Verify API implementation through integration tests with https://www.browserstack.com/guide/what-is-bdd[Behaviour Driven Development (BDD)] -using Spring Boot, https://testcontainers.com/[Testcontainers], and https://rest-assured.io/[RestAssured]. - - -== Background - -RestAssured provide the convenience to test REST API in BDD style. It is very useful to test API implementation in Spring Boot application. -Provided that its API involved common BDD keywords such as `given`, `when` and `then`. - -In this example we will implement three features: - -[start=1] -. User creation -. User retrieval by username -. User deletion - -We will implement test scenarios before implementing the actual API. - -== User Creation - -We will implement two scenarios - create with an available username and create with an unavailable username. - -[source,java] ----- -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class CreateUserTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given provided username is available When I create a User Then response status should be Created") - void availableUsername() { - var content = """ - { - "name": "Rashidi Zin", - "username": "rashidi.zin" - } - """; - - given() - .contentType(JSON) - .body(content) - .when() - .post("/users") - .then().assertThat() - .statusCode(equalTo(SC_CREATED)); - } - - @Test - @DisplayName("Given the username zaid.zin is unavailable When I create a User Then response status should be Bad Request") - void unavailableUsername() { - var content = """ - { - "name": "Zaid Zin", - "username": "zaid.zin" - } - """; - - given() - .contentType(JSON) - .body(content) - .when() - .post("/users") - .then().assertThat() - .statusCode(equalTo(SC_BAD_REQUEST)); - } - -} ----- - -In the implementation above. Testcontainers is used to simulate actual MongoDB and -link:{url-quickref}/src/test/java/zin/rashidi/boot/test/restassured/user/UserCreationTestExecutionListener.java[UserCreationTestExecutionListener] will load data into the database. -The data will be used to validate the second scenario. - -Next we will implement the API which will ensure that scenarios above will pass. We will start our implementation to fix the first failing -scenario - create with an available username. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @PostMapping("/users") - @ResponseStatus(CREATED) - public void create(@RequestBody UserRequest request) { - repository.save(new User(request.name(), request.username())); - } - -} ----- - -The implementation above should be sufficient to fix our first scenario. We will run the test again to ensure that it passes. Next is to -fix our second scenario - create with an unavailable username. - -Given that we do not have any validation in place, the second scenario will fail. We will add validation to ensure that the username is -unique. We will start by implementing a `Repository` method to validate if the username exists. - -[source,java] ----- -interface UserRepository extends MongoRepository { - - boolean existsByUsername(String username); - -} ----- - -Next, we will use `existsByUsername` to validate if the username exists before saving the user. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @PostMapping("/users") - @ResponseStatus(CREATED) - public void create(@RequestBody UserRequest request) { - if (repository.existsByUsername(request.username())) { - throw new IllegalArgumentException("Username already exists"); - } - - repository.save(new User(request.name(), request.username())); - } - -} ----- - -This, however, is insufficient as the server will throw `500 Internal Server Error` when the username already exists. We will add -`@ExceptionHandler` to handle the exception which converts it to `BAD REQUEST`. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @PostMapping("/users") - @ResponseStatus(CREATED) - public void create(@RequestBody UserRequest request) { - if (repository.existsByUsername(request.username())) { - throw new IllegalArgumentException("Username already exists"); - } - - repository.save(new User(request.name(), request.username())); - } - - @ExceptionHandler - @ResponseStatus(BAD_REQUEST) - public void handleIllegalArgumentException(IllegalArgumentException ignored) { - } - -} ----- - -Now we will run link:{url-quickref}/src/test/java/zin/rashidi/boot/test/restassured/user/CreateUserTests.java[CreateUserTests] again to ensure that both scenarios pass. Next, we will follow the same approach to implement the API for user retrieval by username. - -== User Retrieval by Username - -In link:{url-quickref}/src/test/java/zin/rashidi/boot/test/restassured/user/FindUserByUsernameTests.java[FindUserByUsernameTests], we will implement two scenarios - find with an available username and find with an unavailable username. - -[source,java] ----- -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class FindUserByUsernameTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given username zaid.zin exists When I find a User Then response status should be OK and User should be returned") - void findByExistingUsername() { - given() - .contentType(JSON) - .when() - .get("/users/{username}", "zaid.zin") - .then().assertThat() - .statusCode(equalTo(SC_OK)) - .body("name", equalTo("Zaid Zin")) - .body("username", equalTo("zaid.zin")); - } - - @Test - @DisplayName("Given there is no User with username rashidi.zin When I find a User Then response status should be Not Found") - void findByNonExistingUsername() { - given() - .contentType(JSON) - .when() - .get("/users/{username}", "rashidi.zin") - .then().assertThat() - .statusCode(equalTo(SC_NOT_FOUND)); - } - -} ----- - -As you can see, `findByExistingUsername` validates the response body as well as HTTP response. Given that the user exists then the response body should contain the user's name and username. The HTTP response should be `200 OK`. - -While in the event requested `username` does not exist then the HTTP response should be `404 Not Found`. - -We will start by implementing a `Repository` method which will retrieve requested username. - -[source,java] ----- -interface UserRepository extends MongoRepository { - - Optional findByUsername(String username); - -} ----- - -link:{url-quickref}/src/main/java/zin/rashidi/boot/test/restassured/user/UserReadOnly.java[UserReadOnly] is a read-only projection of -`User` which will be used to retrieve the user's name and username. - -Then we will implement the API to fix the scenarios above. We will start with the first scenario - find with an available username. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @GetMapping("/users/{username}") - public UserReadOnly findByUsername(@PathVariable String username) { - return repository.findByUsername(username).orElseThrow(); - } - -} ----- - -The implementation above should be sufficient to fix our first scenario. We will run the test again to ensure that it passes. -Next is to fix our second scenario - find with an unavailable username. - -As for now, the second scenario will fail. We will add `@ExceptionHandler` to handle the exception which converts it to `NOT FOUND`. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @GetMapping("/users/{username}") - public UserReadOnly findByUsername(@PathVariable String username) { - return repository.findByUsername(username).orElseThrow(); - } - - @ExceptionHandler - @ResponseStatus(NOT_FOUND) - public void handleNoSuchElementException(NoSuchElementException ignored) { - } - -} ----- - -Now we will run link:{url-quickref}/src/test/java/zin/rashidi/boot/test/restassured/user/FindUserByUsernameTests.java[FindUserByUsernameTests] -again to ensure that both scenarios pass. Next, we will follow the same approach to implement the API for user deletion. - -== User Deletion - -For User Deletion, the action requires a valid `id`. However, since we are going to utilise data stored by `Testcontainers`, we are required -to retrieve the existing user's `id` first. Then we will perform the deletion. - -We will implement two scenarios - delete with an available `id` and delete with an non-existing `id`. - -[source,java] ----- -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class DeleteUserTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given username zaid.zin exists When I delete with its id Then response status should be No Content") - void deleteWithValidId() { - String id = get("/users/{username}", "zaid.zin").path("id"); - - when() - .delete("/users/{id}", id) - .then().assertThat() - .statusCode(equalTo(SC_NO_CONTENT)); - } - - @Test - @DisplayName("When I trigger delete with a non-existing ID Then response status should be Not Found") - void deleteWithNonExistingId() { - when() - .delete("/users/{id}", "5f9b0a9b9d9b4a0a9d9b4a0a") - .then().assertThat() - .statusCode(equalTo(SC_NOT_FOUND)); - } - -} ----- - -As you can see, in `deleteWithValidId` we are retrieving the existing user's `id` first. - -[source,java] ----- -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class DeleteUserTests { - - @Test - @DisplayName("Given username zaid.zin exists When I delete with its id Then response status should be No Content") - void deleteWithValidId() { - String id = get("/users/{username}", "zaid.zin").path("id"); - - when() - .delete("/users/{id}", id) - .then().assertThat() - .statusCode(equalTo(SC_NO_CONTENT)); - } - -} ----- - -Once we have the `id`, we will perform the deletion. Next, we will implement the API to fix the scenarios above. We will start with the first scenario - delete with an available `id`. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @DeleteMapping("/users/{id}") - @ResponseStatus(NO_CONTENT) - public void deleteById(@PathVariable ObjectId id) { - repository.findById(id).ifPresent(repository::delete); - } - -} ----- - -The implementation above should be sufficient to fix our first scenario. We will run the test again to ensure that it passes. Next is to fix our second scenario - delete with an non-existing `id`. We're expecting `404 Not Found` in this scenario. We can achieve this with slight modification to `deleteById` method. - -[source,java] ----- -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @DeleteMapping("/users/{id}") - @ResponseStatus(NO_CONTENT) - public void deleteById(@PathVariable ObjectId id) { - repository.findById(id).ifPresentOrElse(repository::delete, () -> { throw new NoSuchElementException(); }); - } - -} ----- - -Since we have already implement `@ExceptionHandler` to handle `NoSuchElementException`, this implementation should be sufficient to fix our -second scenario. We will run the test again to ensure that it passes. - -== Conclusion - -I have always preferred RestAssured as it allows me to test API implementation in BDD style. Given that I can decouple my tests with the -production code, I can ensure that my tests are not affected by the implementation details. - -As you can see from tests above. None of the tests uses production code. This is very useful when I need to refactor my -code. I can refactor my code without worrying that my tests will break. As long as the API contract remains the same, my tests will pass. diff --git a/test-rest-assured/build.gradle.kts b/test-rest-assured/build.gradle.kts deleted file mode 100644 index 7e676fb6..00000000 --- a/test-rest-assured/build.gradle.kts +++ /dev/null @@ -1,32 +0,0 @@ -plugins { - java - id("org.springframework.boot") version "3.5.7" - id("io.spring.dependency-management") version "1.1.7" -} - -group = "zin.rashidi.boot" -version = "0.0.1-SNAPSHOT" - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(25)) - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation("org.springframework.boot:spring-boot-starter-data-mongodb") - implementation("org.springframework.boot:spring-boot-starter-web") - testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("org.springframework.boot:spring-boot-testcontainers") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:mongodb") - testImplementation("io.rest-assured:rest-assured") -} - -tasks.named("test") { - useJUnitPlatform() -} \ No newline at end of file diff --git a/test-rest-assured/settings.gradle b/test-rest-assured/settings.gradle deleted file mode 100644 index 4e350988..00000000 --- a/test-rest-assured/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'test-rest-assured' diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/TestRestAssuredApplication.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/TestRestAssuredApplication.java deleted file mode 100644 index f2979c69..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/TestRestAssuredApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package zin.rashidi.boot.test.restassured; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class TestRestAssuredApplication { - - public static void main(String[] args) { - SpringApplication.run(TestRestAssuredApplication.class, args); - } - -} diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/User.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/User.java deleted file mode 100644 index d5da66e4..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/User.java +++ /dev/null @@ -1,21 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.core.mapping.Document; - -/** - * @author Rashidi Zin - */ -@Document -class User { - - private ObjectId id; - private final String name; - private final String username; - - public User(String name, String username) { - this.name = name; - this.username = username; - } - -} diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserReadOnly.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserReadOnly.java deleted file mode 100644 index 212e67df..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserReadOnly.java +++ /dev/null @@ -1,12 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import org.bson.types.ObjectId; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; - -/** - * @author Rashidi Zin - */ -record UserReadOnly(@JsonSerialize(using = ToStringSerializer.class) ObjectId id, String name, String username) { -} diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRepository.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRepository.java deleted file mode 100644 index 1948de81..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import java.util.Optional; - -import org.bson.types.ObjectId; -import org.springframework.data.mongodb.repository.MongoRepository; - -/** - * @author Rashidi Zin - */ -interface UserRepository extends MongoRepository { - - boolean existsByUsername(String username); - - Optional findByUsername(String username); - -} diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRequest.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRequest.java deleted file mode 100644 index 0a2811d7..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -/** - * @author Rashidi Zin - */ -record UserRequest(String name, String username) { -} diff --git a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserResource.java b/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserResource.java deleted file mode 100644 index d7c2f0c7..00000000 --- a/test-rest-assured/src/main/java/zin/rashidi/boot/test/restassured/user/UserResource.java +++ /dev/null @@ -1,63 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.CREATED; -import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.springframework.http.HttpStatus.NO_CONTENT; - -import java.util.NoSuchElementException; - -import org.bson.types.ObjectId; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Rashidi Zin - */ -@RestController -class UserResource { - - private final UserRepository repository; - - UserResource(UserRepository repository) { - this.repository = repository; - } - - @PostMapping("/users") - @ResponseStatus(CREATED) - public void create(@RequestBody UserRequest request) { - if (repository.existsByUsername(request.username())) { - throw new IllegalArgumentException("Username already exists"); - } - - repository.save(new User(request.name(), request.username())); - } - - @GetMapping("/users/{username}") - public UserReadOnly findByUsername(@PathVariable String username) { - return repository.findByUsername(username).orElseThrow(); - } - - @DeleteMapping("/users/{id}") - @ResponseStatus(NO_CONTENT) - public void deleteById(@PathVariable ObjectId id) { - repository.findById(id).ifPresentOrElse(repository::delete, () -> { throw new NoSuchElementException(); }); - } - - @ExceptionHandler - @ResponseStatus(BAD_REQUEST) - public void handleIllegalArgumentException(IllegalArgumentException ignored) { - } - - @ExceptionHandler - @ResponseStatus(NOT_FOUND) - public void handleNoSuchElementException(NoSuchElementException ignored) { - } - -} diff --git a/test-rest-assured/src/main/resources/application.properties b/test-rest-assured/src/main/resources/application.properties deleted file mode 100644 index 8b137891..00000000 --- a/test-rest-assured/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/TestTestRestAssuredApplication.java b/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/TestTestRestAssuredApplication.java deleted file mode 100644 index aa7bcb9c..00000000 --- a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/TestTestRestAssuredApplication.java +++ /dev/null @@ -1,23 +0,0 @@ -package zin.rashidi.boot.test.restassured; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.utility.DockerImageName; - -@TestConfiguration(proxyBeanMethods = false) -public class TestTestRestAssuredApplication { - - @Bean - @ServiceConnection - MongoDBContainer mongoDbContainer() { - return new MongoDBContainer(DockerImageName.parse("mongo:latest")); - } - - public static void main(String[] args) { - SpringApplication.from(TestRestAssuredApplication::main).with(TestTestRestAssuredApplication.class).run(args); - } - -} diff --git a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/CreateUserTests.java b/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/CreateUserTests.java deleted file mode 100644 index 4390145f..00000000 --- a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/CreateUserTests.java +++ /dev/null @@ -1,78 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import io.restassured.RestAssured; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.test.context.TestExecutionListeners; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.apache.http.HttpStatus.SC_BAD_REQUEST; -import static org.apache.http.HttpStatus.SC_CREATED; -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS; - -/** - * @author Rashidi Zin - */ -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class CreateUserTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given provided username is available When I create a User Then response status should be Created") - void availableUsername() { - var content = """ - { - "name": "Rashidi Zin", - "username": "rashidi.zin" - } - """; - - given() - .contentType(JSON) - .body(content) - .when() - .post("/users") - .then().assertThat() - .statusCode(equalTo(SC_CREATED)); - } - - @Test - @DisplayName("Given the username zaid.zin is unavailable When I create a User Then response status should be Bad Request") - void unavailableUsername() { - var content = """ - { - "name": "Zaid Zin", - "username": "zaid.zin" - } - """; - - given() - .contentType(JSON) - .body(content) - .when() - .post("/users") - .then().assertThat() - .statusCode(equalTo(SC_BAD_REQUEST)); - } - -} diff --git a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/DeleteUserTests.java b/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/DeleteUserTests.java deleted file mode 100644 index 589c5f71..00000000 --- a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/DeleteUserTests.java +++ /dev/null @@ -1,60 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import io.restassured.RestAssured; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.test.context.TestExecutionListeners; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import static io.restassured.RestAssured.get; -import static io.restassured.RestAssured.when; -import static org.apache.http.HttpStatus.SC_NOT_FOUND; -import static org.apache.http.HttpStatus.SC_NO_CONTENT; -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS; - -/** - * @author Rashidi Zin - */ -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class DeleteUserTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given username zaid.zin exists When I delete with its id Then response status should be No Content") - void deleteWithValidId() { - String id = get("/users/{username}", "zaid.zin").path("id"); - - when() - .delete("/users/{id}", id) - .then().assertThat() - .statusCode(equalTo(SC_NO_CONTENT)); - } - - @Test - @DisplayName("When I trigger delete with a non-existing ID Then response status should be Not Found") - void deleteWithNonExistingId() { - when() - .delete("/users/{id}", "5f9b0a9b9d9b4a0a9d9b4a0a") - .then().assertThat() - .statusCode(equalTo(SC_NOT_FOUND)); - } - -} diff --git a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/FindUserByUsernameTests.java b/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/FindUserByUsernameTests.java deleted file mode 100644 index 758c8b87..00000000 --- a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/FindUserByUsernameTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import io.restassured.RestAssured; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.test.context.TestExecutionListeners; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static org.apache.http.HttpStatus.SC_NOT_FOUND; -import static org.apache.http.HttpStatus.SC_OK; -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; -import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS; - -/** - * @author Rashidi Zin - */ -@Testcontainers -@TestExecutionListeners(listeners = UserCreationTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS) -@SpringBootTest(webEnvironment = RANDOM_PORT) -class FindUserByUsernameTests { - - @Container - @ServiceConnection - private static final MongoDBContainer mongo = new MongoDBContainer("mongo:latest"); - - @BeforeAll - static void port(@LocalServerPort int port) { - RestAssured.port = port; - } - - @Test - @DisplayName("Given username zaid.zin exists When I find a User Then response status should be OK and User should be returned") - void findByExistingUsername() { - given() - .contentType(JSON) - .when() - .get("/users/{username}", "zaid.zin") - .then().assertThat() - .statusCode(equalTo(SC_OK)) - .body("name", equalTo("Zaid Zin")) - .body("username", equalTo("zaid.zin")); - } - - @Test - @DisplayName("Given there is no User with username rashidi.zin When I find a User Then response status should be Not Found") - void findByNonExistingUsername() { - given() - .contentType(JSON) - .when() - .get("/users/{username}", "rashidi.zin") - .then().assertThat() - .statusCode(equalTo(SC_NOT_FOUND)); - } - -} diff --git a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/UserCreationTestExecutionListener.java b/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/UserCreationTestExecutionListener.java deleted file mode 100644 index 79f4d72c..00000000 --- a/test-rest-assured/src/test/java/zin/rashidi/boot/test/restassured/user/UserCreationTestExecutionListener.java +++ /dev/null @@ -1,24 +0,0 @@ -package zin.rashidi.boot.test.restassured.user; - -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.support.AbstractTestExecutionListener; - -/** - * @author Rashidi Zin - */ -class UserCreationTestExecutionListener extends AbstractTestExecutionListener { - - @Override - public void beforeTestClass(TestContext testContext) { - var mongo = testContext.getApplicationContext().getBean(MongoOperations.class); - - mongo.save(new User("Zaid Zin", "zaid.zin")); - } - - @Override - public int getOrder() { - return HIGHEST_PRECEDENCE; - } - -} diff --git a/test-slice-tests-rest/build.gradle.kts b/test-slice-tests-rest/build.gradle.kts index 695922fa..51119c0b 100644 --- a/test-slice-tests-rest/build.gradle.kts +++ b/test-slice-tests-rest/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -19,15 +19,17 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-data-jpa-test:4.0.2") + implementation("org.springframework.boot:spring-boot-starter-webmvc") + implementation("org.springframework.boot:spring-boot-starter-webmvc-test:4.0.2") implementation("org.springframework.boot:spring-boot-starter-security") - testImplementation("org.springframework.security:spring-security-test") + testImplementation("org.springframework.boot:spring-boot-starter-security-test") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-testcontainers") testImplementation("org.springframework.batch:spring-batch-test") - testImplementation("org.testcontainers:junit-jupiter") - testImplementation("org.testcontainers:postgresql") + testImplementation("org.testcontainers:testcontainers-junit-jupiter") + testImplementation("org.testcontainers:testcontainers-postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/test-slice-tests-rest/settings.gradle b/test-slice-tests-rest/settings.gradle index abc97dd1..3d08cf9a 100644 --- a/test-slice-tests-rest/settings.gradle +++ b/test-slice-tests-rest/settings.gradle @@ -1 +1,5 @@ rootProject.name = 'test-slice-tests-rest' + +dependencies { + runtimeOnly "org.springframework:spring-context:7.0.3" +} diff --git a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/TestcontainersConfiguration.java b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/TestcontainersConfiguration.java index 473caa72..ce7fae89 100644 --- a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/TestcontainersConfiguration.java +++ b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/TestcontainersConfiguration.java @@ -3,7 +3,7 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) @@ -11,8 +11,8 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection - PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); } } diff --git a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/FindByUsernameTests.java b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/FindByUsernameTests.java index dad878a1..6051dd24 100644 --- a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/FindByUsernameTests.java +++ b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/FindByUsernameTests.java @@ -3,8 +3,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.resttestclient.TestRestTemplate; import org.springframework.context.annotation.Import; import org.springframework.test.context.jdbc.Sql; import zin.rashidi.boot.test.slices.TestcontainersConfiguration; @@ -18,6 +19,7 @@ /** * @author Rashidi Zin */ +@AutoConfigureTestRestTemplate @Import(TestcontainersConfiguration.class) @SpringBootTest(webEnvironment = RANDOM_PORT, properties = { "spring.jpa.hibernate.ddl-auto=create-drop", diff --git a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserRepositoryTests.java b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserRepositoryTests.java index 37da6957..0959ebfa 100644 --- a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserRepositoryTests.java +++ b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserRepositoryTests.java @@ -3,12 +3,12 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.test.context.jdbc.Sql; -import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.postgresql.PostgreSQLContainer; import org.testcontainers.utility.DockerImageName; import static org.assertj.core.api.Assertions.assertThat; @@ -23,7 +23,7 @@ class UserRepositoryTests { @Container @ServiceConnection - private static final PostgreSQLContainer postgresql = new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest")); + private static final PostgreSQLContainer postgresql = new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); @Autowired private UserRepository repository; diff --git a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserResourceTests.java b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserResourceTests.java index 95fd4195..03377ab9 100644 --- a/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserResourceTests.java +++ b/test-slice-tests-rest/src/test/java/zin/rashidi/boot/test/slices/user/UserResourceTests.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.test.context.support.WithMockUser; diff --git a/web-rest-client/build.gradle.kts b/web-rest-client/build.gradle.kts index 2f025664..d17b3646 100644 --- a/web-rest-client/build.gradle.kts +++ b/web-rest-client/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -18,7 +18,9 @@ repositories { } dependencies { - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-restclient:4.0.2") + implementation("org.springframework.boot:spring-boot-starter-restclient-test:4.0.2") + implementation("org.springframework.boot:spring-boot-starter-webmvc") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/web-rest-client/settings.gradle b/web-rest-client/settings.gradle index 7e3c962a..5b255bb3 100644 --- a/web-rest-client/settings.gradle +++ b/web-rest-client/settings.gradle @@ -1 +1,5 @@ rootProject.name = 'web-rest-client' + +dependencies { + runtimeOnly "org.springframework:spring-webmvc:7.0.3" +} diff --git a/web-rest-client/src/main/java/zin/rashidi/boot/web/restclient/user/UserRestRepository.java b/web-rest-client/src/main/java/zin/rashidi/boot/web/restclient/user/UserRestRepository.java index fb82dfbe..f7e1d4c8 100644 --- a/web-rest-client/src/main/java/zin/rashidi/boot/web/restclient/user/UserRestRepository.java +++ b/web-rest-client/src/main/java/zin/rashidi/boot/web/restclient/user/UserRestRepository.java @@ -36,7 +36,7 @@ public List findAll() { public User findById(Long id) { return restClient.get().uri("/{id}", id) .retrieve() - .onStatus(HttpStatusCode::is4xxClientError, ((_, _) -> { + .onStatus(HttpStatusCode::is4xxClientError, ((req, resp) -> { throw new UserNotFoundException(); })) .body(User.class); diff --git a/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/post/PostRepositoryTests.java b/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/post/PostRepositoryTests.java index fee5faa8..3d3473b2 100644 --- a/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/post/PostRepositoryTests.java +++ b/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/post/PostRepositoryTests.java @@ -1,13 +1,13 @@ package zin.rashidi.boot.web.restclient.post; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; +import org.springframework.boot.restclient.test.autoconfigure.RestClientTest; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.test.web.client.MockRestServiceServer; +import tools.jackson.core.JacksonException; import zin.rashidi.boot.web.restclient.post.PostRepositoryConfiguration.PostErrorResponseHandler.PostNotFoundException; import java.util.List; @@ -36,7 +36,7 @@ class PostRepositoryTests { @Test @DisplayName("When requesting for all posts then response should contain all posts available") - void findAll() throws JsonProcessingException { + void findAll() throws JacksonException { var content = mapper.writeValueAsString(posts()); mockServer.expect(requestTo("https://jsonplaceholder.typicode.com/posts")).andRespond(withSuccess(content, APPLICATION_JSON)); @@ -48,7 +48,7 @@ void findAll() throws JsonProcessingException { @Test @DisplayName("Given a post with requested id is available When requested Then a post with the id should be returned") - void findById() throws JsonProcessingException { + void findById() throws JacksonException { var content = mapper.writeValueAsString(new Post(1L, 84L, "Spring Web: REST Clients Example with RESTClient", "An example of using RESTClient")); mockServer.expect(requestTo("https://jsonplaceholder.typicode.com/posts/1")).andRespond(withSuccess(content, APPLICATION_JSON)); diff --git a/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/user/UserRepositoryTests.java b/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/user/UserRepositoryTests.java index 680edddb..5f807baf 100644 --- a/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/user/UserRepositoryTests.java +++ b/web-rest-client/src/test/java/zin/rashidi/boot/web/restclient/user/UserRepositoryTests.java @@ -1,12 +1,12 @@ package zin.rashidi.boot.web.restclient.user; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; +import org.springframework.boot.restclient.test.autoconfigure.RestClientTest; import org.springframework.test.web.client.MockRestServiceServer; +import tools.jackson.core.JacksonException; import zin.rashidi.boot.web.restclient.user.UserRestRepository.UserNotFoundException; import java.net.URI; @@ -36,7 +36,7 @@ class UserRepositoryTests { @Test @DisplayName("When findAll Then all users should be returned") - void findAll() throws JsonProcessingException { + void findAll() throws JacksonException { var response = mapper.writeValueAsString(List.of( new User(84L, "Rashidi Zin", "rashidi.zin", "rashidi@zin.my", URI.create("rashidi.zin.my")), new User(87L, "Zaid Zin", "zaid.zin", "zaid@zin.my", URI.create("zaid.zin.my")) @@ -51,7 +51,7 @@ void findAll() throws JsonProcessingException { @Test @DisplayName("When an id is provided Then user with the id should be returned") - void findById() throws JsonProcessingException { + void findById() throws JacksonException { var response = mapper.writeValueAsString( new User(84L, "Rashidi Zin", "rashidi.zin", "rashidi@zin.my", URI.create("rashidi.zin.my")) ); diff --git a/web-thymeleaf-xss/build.gradle.kts b/web-thymeleaf-xss/build.gradle.kts index 838b5453..0598f75b 100644 --- a/web-thymeleaf-xss/build.gradle.kts +++ b/web-thymeleaf-xss/build.gradle.kts @@ -1,6 +1,6 @@ plugins { java - id("org.springframework.boot") version "3.5.7" + id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" } @@ -20,10 +20,11 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-webmvc") + implementation("org.springframework.boot:spring-boot-starter-webmvc-test:4.0.2") implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6") testImplementation("org.springframework.boot:spring-boot-starter-test") - testImplementation("org.springframework.security:spring-security-test") + testImplementation("org.springframework.boot:spring-boot-starter-security-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } diff --git a/web-thymeleaf-xss/settings.gradle.kts b/web-thymeleaf-xss/settings.gradle.kts index ad0e708c..365d18a8 100644 --- a/web-thymeleaf-xss/settings.gradle.kts +++ b/web-thymeleaf-xss/settings.gradle.kts @@ -1 +1,5 @@ rootProject.name = "web-thymeleaf-xss" + +dependencies { + runtimeOnly("org.springframework:spring-webmvc:7.0.3") +} diff --git a/web-thymeleaf-xss/src/test/java/zin/rashidi/web/xss/greet/GreetResourceTests.java b/web-thymeleaf-xss/src/test/java/zin/rashidi/web/xss/greet/GreetResourceTests.java index 4e6b3615..0228669c 100644 --- a/web-thymeleaf-xss/src/test/java/zin/rashidi/web/xss/greet/GreetResourceTests.java +++ b/web-thymeleaf-xss/src/test/java/zin/rashidi/web/xss/greet/GreetResourceTests.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.test.web.servlet.assertj.MockMvcTester;