diff --git a/09-01-result/.gitignore b/09-01-result/.gitignore index 9d5c07a..d4c3bf4 100644 --- a/09-01-result/.gitignore +++ b/09-01-result/.gitignore @@ -2,3 +2,4 @@ .gradle build README.md +bin diff --git a/09-01-result/bin/main/application-test.yml b/09-01-result/bin/main/application-test.yml deleted file mode 100644 index 1c13311..0000000 --- a/09-01-result/bin/main/application-test.yml +++ /dev/null @@ -1,14 +0,0 @@ -spring: - datasource: - url: jdbc:tc:postgresql:14.5:///course_database - username: course_username - password: course_password - driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect - hibernate: - ddl-auto: validate - open-in-view: false - diff --git a/09-01-result/bin/main/application.yml b/09-01-result/bin/main/application.yml deleted file mode 100644 index 8927cb8..0000000 --- a/09-01-result/bin/main/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - datasource: - url: "jdbc:postgresql://${POSTGRE_URL:localhost}:${POSTGRE_PORT:5432}/course_database" - username: ${POSTGRE_USERNAME:course_username} - password: ${POSTGRE_PASSWORD:course_password} - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect - hibernate: - ddl-auto: validate - open-in-view: false diff --git a/09-01-result/bin/main/com/codely/Application.kt b/09-01-result/bin/main/com/codely/Application.kt deleted file mode 100644 index 8ad1ecf..0000000 --- a/09-01-result/bin/main/com/codely/Application.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.codely - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -class Application - -fun main(args: Array) { - runApplication(*args) -} diff --git a/09-01-result/bin/main/com/codely/config/DatabaseConfig.kt b/09-01-result/bin/main/com/codely/config/DatabaseConfig.kt deleted file mode 100644 index db31c7e..0000000 --- a/09-01-result/bin/main/com/codely/config/DatabaseConfig.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.codely.config - -import com.codely.course.infrastructure.persistence.PostgreCourseRepository -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate - -@Configuration -class DatabaseConfig { - - @Bean - fun courseRepository(jdbcTemplate: NamedParameterJdbcTemplate) = PostgreCourseRepository(jdbcTemplate) -} diff --git a/09-01-result/bin/main/com/codely/config/DependencyInjectionConf.kt b/09-01-result/bin/main/com/codely/config/DependencyInjectionConf.kt deleted file mode 100644 index 39a764c..0000000 --- a/09-01-result/bin/main/com/codely/config/DependencyInjectionConf.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.codely.config - -import com.codely.course.application.CourseCreator -import com.codely.course.application.find.CourseFinder -import com.codely.course.domain.CourseRepository -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -@Configuration -class DependencyInjectionConf { - - @Bean - fun courseCreator(courseRepository: CourseRepository) = CourseCreator(courseRepository) - - @Bean - fun courseFinder(courseRepository: CourseRepository) = CourseFinder(courseRepository) -} diff --git a/09-01-result/bin/main/db/migration/V1.0.0__course_table.sql b/09-01-result/bin/main/db/migration/V1.0.0__course_table.sql deleted file mode 100644 index ae0e6c9..0000000 --- a/09-01-result/bin/main/db/migration/V1.0.0__course_table.sql +++ /dev/null @@ -1,5 +0,0 @@ -create table if not exists course( - id varchar(64) primary key, - name varchar(255) not null, - created_at TIMESTAMP not null -); diff --git a/09-01-result/bin/test-integration/com/codely/course/acceptance/GetFindCourseAcceptanceTestRestAssure.kt b/09-01-result/bin/test-integration/com/codely/course/acceptance/GetFindCourseAcceptanceTestRestAssure.kt deleted file mode 100644 index 9342e9c..0000000 --- a/09-01-result/bin/test-integration/com/codely/course/acceptance/GetFindCourseAcceptanceTestRestAssure.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.codely.course.acceptance - -import com.codely.common.course.CourseMother -import com.codely.course.infrastructure.persistence.PostgreCourseRepository -import com.codely.shared.acceptance.BaseAcceptanceTest -import com.codely.shared.acceptance.isEqualToJson -import io.restassured.http.ContentType -import io.restassured.module.kotlin.extensions.Extract -import io.restassured.module.kotlin.extensions.Given -import io.restassured.module.kotlin.extensions.Then -import io.restassured.module.kotlin.extensions.When -import java.time.LocalDateTime -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.http.HttpStatus -import org.springframework.test.context.jdbc.Sql - -class GetFindCourseAcceptanceTestRestAssure : BaseAcceptanceTest() { - - @Autowired - private lateinit var courseRepository: PostgreCourseRepository - - @Test - @Sql("classpath:db/fixtures/find/add-course-data.sql") - fun `should find course successfully with fixture`() { - When { - get("/course/${course.id.value}") - } Then { - statusCode(HttpStatus.OK.value()) - } Extract { - body().asString().isEqualToJson(expectedCourseResponse) - } - } - - @Test - fun `should find course successfully with course creation`() { - Given { - `an existin course`() - contentType(ContentType.JSON) - body("") - } When { - get("/course/${course.id.value}") - } Then { - statusCode(HttpStatus.OK.value()) - } Extract { - body().asString().isEqualToJson(expectedCourseResponse) - } - } - - private fun `an existin course`() { - courseRepository.save(course) - } - - companion object { - private val now = LocalDateTime.parse("2022-08-31T09:07:36") - private val course = CourseMother.sample( - id = "f2fe1e4e-1e8f-493b-ac67-2c88090cae0a", - name = "Saved course", - createdAt = now - ) - private val expectedCourseResponse = """ - { - "id": "${course.id.value}", - "name": "${course.name.value}", - "createdAt": "$now" - } - """.trimIndent() - } -} diff --git a/09-01-result/bin/test-integration/com/codely/course/acceptance/PostCreateCourseAcceptanceTestRestAssure.kt b/09-01-result/bin/test-integration/com/codely/course/acceptance/PostCreateCourseAcceptanceTestRestAssure.kt deleted file mode 100644 index 2bb951f..0000000 --- a/09-01-result/bin/test-integration/com/codely/course/acceptance/PostCreateCourseAcceptanceTestRestAssure.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.codely.course.acceptance - -import com.codely.shared.acceptance.BaseAcceptanceTest -import io.restassured.http.ContentType -import io.restassured.module.kotlin.extensions.Given -import io.restassured.module.kotlin.extensions.Then -import io.restassured.module.kotlin.extensions.When -import org.junit.jupiter.api.Test -import org.springframework.http.HttpStatus - -class PostCreateCourseAcceptanceTestRestAssure : BaseAcceptanceTest() { - - @Test - fun `should create a course successfully`() { - Given { - contentType(ContentType.JSON) - body( - """ - { - "id": "97fa5af4-bd81-45d5-974f-d5a3970af252", - "name": "Test Acceptance" - } - """ - ) - } When { - post("/course") - } Then { - statusCode(HttpStatus.CREATED.value()) - } - } -} diff --git a/09-01-result/bin/test-integration/com/codely/course/persistence/PostgreCourseRepositoryTest.kt b/09-01-result/bin/test-integration/com/codely/course/persistence/PostgreCourseRepositoryTest.kt deleted file mode 100644 index 6f43e30..0000000 --- a/09-01-result/bin/test-integration/com/codely/course/persistence/PostgreCourseRepositoryTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.codely.course.persistence - -import com.codely.common.course.CourseMother -import com.codely.course.domain.CourseId -import com.codely.course.infrastructure.persistence.PostgreCourseRepository -import com.codely.shared.persistence.BaseIntegrationTest -import kotlin.test.assertEquals -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest - -@DataJpaTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class PostgreCourseRepositoryTest : BaseIntegrationTest() { - - @Autowired - private lateinit var repository: PostgreCourseRepository - - @Test - fun `should save a course`() { - val courseId = "13590efb-c181-4c5f-9f95-b768abde13e2" - val courseToSave = CourseMother.sample(id = courseId) - repository.save(courseToSave) - - val courseFromDb = repository.find(CourseId.fromString(courseId)) - - assertEquals(Result.success(courseToSave), courseFromDb) - } -} diff --git a/09-01-result/bin/test-integration/com/codely/shared/acceptance/BaseAcceptanceTest.kt b/09-01-result/bin/test-integration/com/codely/shared/acceptance/BaseAcceptanceTest.kt deleted file mode 100644 index 57f8d70..0000000 --- a/09-01-result/bin/test-integration/com/codely/shared/acceptance/BaseAcceptanceTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.codely.shared.acceptance - -import com.codely.shared.database.PostgresTestUtils -import com.codely.shared.database.TestConfig -import io.mockk.unmockkAll -import io.restassured.RestAssured -import java.io.File -import javax.annotation.PostConstruct -import javax.annotation.PreDestroy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.web.server.LocalServerPort -import org.springframework.context.annotation.Import -import org.springframework.test.context.ActiveProfiles -import org.testcontainers.containers.DockerComposeContainer -import org.testcontainers.containers.wait.strategy.Wait -import org.testcontainers.junit.jupiter.Testcontainers - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@AutoConfigureMockMvc -@ActiveProfiles("test") -@Import(TestConfig::class) -@Testcontainers -class BaseAcceptanceTest { - @LocalServerPort - private val springbootPort: Int = 0 - - @Autowired - private lateinit var postgresTestUtils: PostgresTestUtils - - companion object { - - private const val POSTGRES_PORT = 5432 - val environment: DockerComposeContainer<*> = - DockerComposeContainer(File("docker-compose-test.yml")) - .withExposedService("db", POSTGRES_PORT, Wait.forListeningPort()) - .withLocalCompose(true) - - @PostConstruct - fun start() { - environment.start() - } - - @PreDestroy - fun stop() { - environment.stop() - } - } - - @BeforeEach - fun setUp() { - RestAssured.port = springbootPort - } - - @AfterEach - fun tearDown() { - unmockkAll() - postgresTestUtils.clean() - } -} diff --git a/09-01-result/bin/test-integration/com/codely/shared/acceptance/StringAssertUtils.kt b/09-01-result/bin/test-integration/com/codely/shared/acceptance/StringAssertUtils.kt deleted file mode 100644 index 4b6525b..0000000 --- a/09-01-result/bin/test-integration/com/codely/shared/acceptance/StringAssertUtils.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.codely.shared.acceptance - -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import kotlin.test.assertEquals - -fun String.isEqualToJson(expected: String) { - val objectMapper = jacksonObjectMapper() - assertEquals(objectMapper.readTree(expected), objectMapper.readTree(this)) -} diff --git a/09-01-result/bin/test-integration/com/codely/shared/database/PostgresTestUtils.kt b/09-01-result/bin/test-integration/com/codely/shared/database/PostgresTestUtils.kt deleted file mode 100644 index 633bc06..0000000 --- a/09-01-result/bin/test-integration/com/codely/shared/database/PostgresTestUtils.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.codely.shared.database - -import com.zaxxer.hikari.HikariDataSource -import java.sql.Connection -import java.sql.Statement -import org.springframework.beans.factory.annotation.Autowired - -class PostgresTestUtils { - - @Autowired - private lateinit var datasource: HikariDataSource - - fun clean() { - val connection: Connection = getConnection() - val statement = connection.createStatement() - - val tables: List = getTables(statement) - truncate(tables, statement) - - datasource.evictConnection(connection) - connection.close() - } - - private fun getTables(statement: Statement): List { - val tables: MutableList = java.util.ArrayList() - val rs = statement.executeQuery( - """ - SELECT table_schema, table_name - FROM information_schema.tables WHERE - table_schema = 'public' AND table_name NOT IN ('flyway_schema_history') - """ - ) - while (rs.next()) { - tables.add(rs.getString("table_schema") + "." + rs.getString("table_name")) - } - return tables - } - - private fun truncate(tables: List, statement: Statement) { - for (p in tables) { - statement.addBatch("TRUNCATE TABLE $p;") - } - statement.executeBatch() - } - - private fun getConnection(): Connection { - return datasource.connection - } -} diff --git a/09-01-result/bin/test-integration/com/codely/shared/database/TestConfig.kt b/09-01-result/bin/test-integration/com/codely/shared/database/TestConfig.kt deleted file mode 100644 index 767acb6..0000000 --- a/09-01-result/bin/test-integration/com/codely/shared/database/TestConfig.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.codely.shared.database - -import org.springframework.context.annotation.Bean - -class TestConfig { - - @Bean - fun postgresTestUtils() = PostgresTestUtils() -} diff --git a/09-01-result/bin/test-integration/com/codely/shared/persistence/BaseIntegrationTest.kt b/09-01-result/bin/test-integration/com/codely/shared/persistence/BaseIntegrationTest.kt deleted file mode 100644 index 931927c..0000000 --- a/09-01-result/bin/test-integration/com/codely/shared/persistence/BaseIntegrationTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.codely.shared.persistence - -import com.codely.config.DatabaseConfig -import io.mockk.unmockkAll -import javax.annotation.PostConstruct -import javax.annotation.PreDestroy -import org.junit.jupiter.api.AfterEach -import org.springframework.context.annotation.Import -import org.springframework.test.context.ActiveProfiles -import org.testcontainers.containers.PostgreSQLContainer - -@Import(DatabaseConfig::class) -@ActiveProfiles("test") -open class BaseIntegrationTest { - - companion object { - @JvmStatic - val postgresContainer: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:14.5") - .withDatabaseName("course_database") - .withUsername("course_username") - .withPassword("course_password") - - @PostConstruct - fun start() { - postgresContainer.start() - } - - @PreDestroy - fun stop() { - postgresContainer.stop() - } - } - - @AfterEach - fun tearDown() { - unmockkAll() - } -} diff --git a/09-01-result/bin/test-integration/db/fixtures/find/add-course-data.sql b/09-01-result/bin/test-integration/db/fixtures/find/add-course-data.sql deleted file mode 100644 index 6b0fadb..0000000 --- a/09-01-result/bin/test-integration/db/fixtures/find/add-course-data.sql +++ /dev/null @@ -1 +0,0 @@ -INSERT INTO course(id, name, created_at) VALUES ('f2fe1e4e-1e8f-493b-ac67-2c88090cae0a', 'Saved course', '2022-08-31T09:07:36Z'); diff --git a/09-01-result/contexts/course/src/main/kotlin/com/codely/course/infrastructure/rest/find/GetFindCourseByIdController.kt b/09-01-result/contexts/course/src/main/kotlin/com/codely/course/infrastructure/rest/find/GetFindCourseByIdController.kt index d8f1e5c..ef9b118 100644 --- a/09-01-result/contexts/course/src/main/kotlin/com/codely/course/infrastructure/rest/find/GetFindCourseByIdController.kt +++ b/09-01-result/contexts/course/src/main/kotlin/com/codely/course/infrastructure/rest/find/GetFindCourseByIdController.kt @@ -1,6 +1,7 @@ package com.codely.course.infrastructure.rest.find import com.codely.course.application.find.CourseFinder +import com.codely.course.application.find.CourseResponse import com.codely.course.domain.CourseNotFoundException import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity @@ -14,7 +15,7 @@ class GetFindCourseByIdController(private val courseFinder: CourseFinder) { @GetMapping("/course/{id}") fun execute( @PathVariable id: String - ) = courseFinder.execute(id).fold( + ): ResponseEntity = courseFinder.execute(id).fold( onSuccess = { ResponseEntity.ok().body(it) }, diff --git a/09-01-result/settings.gradle.kts b/09-01-result/settings.gradle.kts index 935d88b..1bce23b 100644 --- a/09-01-result/settings.gradle.kts +++ b/09-01-result/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "07-04-result" +rootProject.name = "09-01-result" include("contexts:course") include("common-test")