Skip to content

Commit

Permalink
Merge pull request #11 from espoon-voltti/integration-test-setup
Browse files Browse the repository at this point in the history
integration test setup
  • Loading branch information
Joosakur authored Nov 16, 2023
2 parents 9df56b8 + 4b58eef commit 306d5df
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 23 deletions.
13 changes: 13 additions & 0 deletions compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ services:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: oppivelvollisuus_it
POSTGRES_USER: oppivelvollisuus
POSTGRES_PASSWORD: postgres

oppivelvollisuus-db-it:
image: postgres:15.4-alpine3.18
ports:
- "6432:5432"
volumes:
- db-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: oppivelvollisuus
POSTGRES_USER: oppivelvollisuus
Expand All @@ -15,3 +26,5 @@ services:
volumes:
db-data:
driver: local
db-it-data:
driver: local
6 changes: 6 additions & 0 deletions service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ repositories {
}

dependencies {
api(kotlin("stdlib"))
implementation("org.jetbrains.kotlin:kotlin-reflect")

implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
Expand All @@ -37,6 +38,9 @@ dependencies {

implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

testImplementation(kotlin("test"))
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

Expand All @@ -49,6 +53,8 @@ tasks.withType<KotlinCompile> {

tasks.withType<Test> {
useJUnitPlatform()
testClassesDirs = sourceSets["test"].output.classesDirs
classpath = sourceSets["test"].runtimeClasspath
}

tasks.getByName<Jar>("jar") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,25 @@ fun main(args: Array<String>) {
}

@RestController
class HelloWorldController {
class MainController {
@Autowired
lateinit var jdbi: Jdbi

data class StudentInput(
val firstName: String,
val lastName: String
)

@PostMapping("/students")
fun createStudent(@RequestBody body: StudentInput): UUID {
val id = UUID.randomUUID()
jdbi.inTransactionUnchecked { tx ->
tx.createUpdate("""
tx.createUpdate(
"""
INSERT INTO students (id, first_name, last_name)
VALUES (:id, :firstName, :lastName)
""")
"""
)
.bind("id", id)
.bindKotlin(body)
.execute()
Expand All @@ -53,6 +56,7 @@ class HelloWorldController {
val firstName: String,
val lastName: String
)

@GetMapping("/students")
fun getStudents(): List<StudentBasics> {
return jdbi.inTransactionUnchecked { tx ->
Expand All @@ -61,14 +65,17 @@ class HelloWorldController {
.list()
}
}

@GetMapping("/students/{id}")
fun getStudent(@PathVariable id: UUID): StudentBasics {
return jdbi.inTransactionUnchecked { tx ->
tx.createQuery("""
tx.createQuery(
"""
SELECT id, first_name, last_name
FROM students
WHERE id = :id
""".trimIndent())
""".trimIndent()
)
.bind("id", id)
.mapTo<StudentBasics>()
.findOne()
Expand All @@ -78,32 +85,37 @@ class HelloWorldController {
}

@PutMapping("/students/{id}")
fun updateStudent(@PathVariable id: UUID, @RequestBody body: StudentInput): Unit {
fun updateStudent(@PathVariable id: UUID, @RequestBody body: StudentInput) {
jdbi.inTransactionUnchecked { tx ->
tx.createUpdate("""
tx.createUpdate(
"""
UPDATE students
SET first_name = :firstName, last_name = :lastName
WHERE id = :id
""")
"""
)
.bind("id", id)
.bindKotlin(body)
.execute()
.also { if(it != 1) error("not found") }
.also { if (it != 1) error("not found") }
}
}

data class StudentCaseInput(
val openedAt: LocalDate,
val info: String
)

@PostMapping("/students/{studentId}/cases")
fun createStudentCase(@PathVariable studentId: UUID, @RequestBody body: StudentCaseInput): UUID {
val id = UUID.randomUUID()
jdbi.inTransactionUnchecked { tx ->
tx.createUpdate("""
tx.createUpdate(
"""
INSERT INTO student_cases (id, student_id, opened_at, info)
VALUES (:id, :studentId, :openedAt, :info)
""")
"""
)
.bind("id", id)
.bind("studentId", studentId)
.bindKotlin(body)
Expand All @@ -118,14 +130,17 @@ class HelloWorldController {
val openedAt: LocalDate,
val info: String
)

@GetMapping("/students/{studentId}/cases")
fun getStudentCasesByStudent(@PathVariable studentId: UUID): List<StudentCase> {
return jdbi.inTransactionUnchecked { tx ->
tx.createQuery("""
tx.createQuery(
"""
SELECT id, student_id, opened_at, info
FROM student_cases
WHERE student_id = :studentId
""".trimIndent())
""".trimIndent()
)
.bind("studentId", studentId)
.mapTo<StudentCase>()
.list()
Expand All @@ -139,18 +154,20 @@ class HelloWorldController {
@RequestBody body: StudentCaseInput
) {
jdbi.inTransactionUnchecked { tx ->
tx.createUpdate("""
tx.createUpdate(
"""
UPDATE student_cases
SET
opened_at = :openedAt,
info = :info
WHERE id = :id AND student_id = :studentId
""")
"""
)
.bind("id", id)
.bind("studentId", studentId)
.bindKotlin(body)
.execute()
.also { if(it != 1) error("not found") }
.also { if (it != 1) error("not found") }
}
}

Expand All @@ -161,17 +178,19 @@ class HelloWorldController {
val lastName: String,
val openedAt: LocalDate
)

@GetMapping("/students-cases")
fun getStudentCases(): List<StudentCaseSummary> {
return jdbi.inTransactionUnchecked { tx ->
tx.createQuery("""
tx.createQuery(
"""
SELECT c.id, student_id, first_name, last_name, opened_at, info
FROM student_cases c
JOIN students s on s.id = c.student_id
""".trimIndent())
""".trimIndent()
)
.mapTo<StudentCaseSummary>()
.list()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package fi.espoo.oppivelvollisuus

import org.jdbi.v3.core.Jdbi
import org.jdbi.v3.core.kotlin.withHandleUnchecked
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInstance
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
abstract class FullApplicationTest {
@Autowired
protected lateinit var jdbi: Jdbi

@BeforeAll
fun beforeAll() {
jdbi.withHandleUnchecked { tx ->
tx.execute(
"""
CREATE OR REPLACE FUNCTION reset_database() RETURNS void AS ${'$'}${'$'}
BEGIN
EXECUTE (
SELECT 'TRUNCATE TABLE ' || string_agg(quote_ident(table_name), ', ') || ' CASCADE'
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
AND table_name <> 'flyway_schema_history'
);
EXECUTE (
SELECT 'SELECT ' || coalesce(string_agg(format('setval(%L, %L, false)', sequence_name, start_value), ', '), '')
FROM information_schema.sequences
WHERE sequence_schema = 'public'
);
END ${'$'}${'$'} LANGUAGE plpgsql;
""".trimIndent()
)
}
}

@BeforeEach
fun beforeEach() {
jdbi.withHandleUnchecked { tx ->
tx.execute("SELECT reset_database()")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package fi.espoo.oppivelvollisuus

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.beans.factory.annotation.Autowired
import kotlin.test.assertEquals

@SpringBootTest
class ServiceApplicationTests {
class ServiceApplicationTests : FullApplicationTest() {
@Autowired
lateinit var controller: MainController

@Test
fun contextLoads() {
fun `get empty list of students`() {
assertEquals(emptyList(), controller.getStudents())
}
}
5 changes: 5 additions & 0 deletions service/src/test/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
spring:
datasource:
url: "jdbc:postgresql://localhost:6432/oppivelvollisuus_it"
username: "oppivelvollisuus"
password: "postgres"

0 comments on commit 306d5df

Please sign in to comment.