Fixed running

This commit is contained in:
Brage Skjønborg 2026-01-05 04:52:13 +01:00
parent 4092cef839
commit b0ca3efc58
9 changed files with 180 additions and 27 deletions

View File

@ -23,7 +23,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 ref: ${{ github.sha }}
base: ${{ github.event.before }}
- name: Detect changes - name: Detect changes
id: filter id: filter

View File

@ -57,6 +57,8 @@ dependencies {
testImplementation(project(":shared:common", configuration = "testArtifacts")) testImplementation(project(":shared:common", configuration = "testArtifacts"))
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
val exposedVersion = "0.61.0"
testImplementation("org.jetbrains.exposed:exposed-core:${exposedVersion}")
} }
tasks.test { tasks.test {

View File

@ -1,15 +1,22 @@
package no.iktdev.mediaprocessing.converter package no.iktdev.mediaprocessing.converter
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
import no.iktdev.eventi.models.Task import no.iktdev.eventi.models.Task
import no.iktdev.mediaprocessing.shared.common.TestBase import no.iktdev.mediaprocessing.shared.common.TestBase
import no.iktdev.mediaprocessing.shared.common.config.DatasourceConfiguration import no.iktdev.mediaprocessing.shared.common.config.DatasourceConfiguration
import no.iktdev.mediaprocessing.shared.common.stores.TaskStore import no.iktdev.mediaprocessing.shared.common.stores.TaskStore
import org.jetbrains.exposed.sql.Database
import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestPropertySource import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.context.junit.jupiter.SpringExtension
import javax.sql.DataSource
@SpringBootTest( @SpringBootTest(
classes = [ConverterApplication::class, classes = [ConverterApplication::class,
@ -18,7 +25,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension
) )
@TestPropertySource(properties = ["spring.flyway.enabled=true"]) @TestPropertySource(properties = ["spring.flyway.enabled=true"])
@ExtendWith(SpringExtension::class) @ExtendWith(SpringExtension::class)
class ConverterApplicationTest: TestBase() { class ConverterApplicationTest : TestBase() {
data class TestTask( data class TestTask(
val success: Boolean val success: Boolean
@ -47,4 +54,28 @@ class ConverterApplicationTest: TestBase() {
assertNotNull(tasksAfter) assertNotNull(tasksAfter)
assert(tasksAfter.isNotEmpty()) assert(tasksAfter.isNotEmpty())
} }
@Test
fun `ExposedInitializer should connect to database`() {
mockkObject(Database)
every {
Database.connect(
any<DataSource>(),
any(),
any(),
any(),
any()
)
} returns mockk()
val context = SpringApplicationBuilder(ConverterApplication::class.java)
.properties("spring.main.web-application-type=none")
.run()
verify(exactly = 1) { Database.connect(any<DataSource>(), any(), any(), any(), any()) }
}
} }

View File

@ -82,7 +82,8 @@ dependencies {
testImplementation("org.mockito:mockito-junit-jupiter:5.11.0") testImplementation("org.mockito:mockito-junit-jupiter:5.11.0")
testImplementation(project(":shared:common", configuration = "testArtifacts")) testImplementation(project(":shared:common", configuration = "testArtifacts"))
testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.boot:spring-boot-starter-test")
val exposedVersion = "0.61.0"
testImplementation("org.jetbrains.exposed:exposed-core:${exposedVersion}")
} }

View File

@ -2,30 +2,44 @@ package no.iktdev.mediaprocessing.coordinator
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import no.iktdev.eventi.events.EventDispatcher import no.iktdev.eventi.events.EventDispatcher
import no.iktdev.eventi.events.EventPollerImplementation import no.iktdev.eventi.events.EventPollerImplementation
import no.iktdev.eventi.events.SequenceDispatchQueue import no.iktdev.eventi.events.SequenceDispatchQueue
import no.iktdev.mediaprocessing.shared.common.stores.EventStore import no.iktdev.mediaprocessing.shared.common.stores.EventStore
import org.springframework.boot.ApplicationArguments import org.springframework.context.SmartLifecycle
import org.springframework.boot.ApplicationRunner import org.springframework.context.annotation.DependsOn
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
@Component @Component
class PollerAdministrator( class PollerAdministrator(
private val eventPoller: EventPoller, private val eventPoller: EventPoller
): ApplicationRunner { ) : SmartLifecycle {
override fun run(args: ApplicationArguments?) {
CoroutineScope(Dispatchers.Default).launch { private var running = false
var job: Job? = null
override fun start() {
job = CoroutineScope(Dispatchers.Default).launch {
eventPoller.start() eventPoller.start()
} }
running = true
} }
override fun stop() {
job?.cancel()
}
override fun isRunning() = running
} }
val sequenceDispatcher = SequenceDispatchQueue(8) val sequenceDispatcher = SequenceDispatchQueue(8)
val dispatcher = EventDispatcher(eventStore = EventStore) val dispatcher = EventDispatcher(eventStore = EventStore)
@Component @Component
@DependsOn("ExposedInit")
class EventPoller: EventPollerImplementation(eventStore = EventStore, dispatchQueue = sequenceDispatcher, dispatcher = dispatcher) { class EventPoller: EventPollerImplementation(eventStore = EventStore, dispatchQueue = sequenceDispatcher, dispatcher = dispatcher) {
} }

View File

@ -0,0 +1,45 @@
package no.iktdev.mediaprocessing
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
import no.iktdev.mediaprocessing.coordinator.CoordinatorApplication
import org.jetbrains.exposed.sql.Database
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension
import javax.sql.DataSource
@ExtendWith(SpringExtension::class)
@SpringBootTest(
classes = [CoordinatorApplication::class],
properties = ["spring.flyway.enabled=true"]
)
class CoordinatorApplicationTest {
@Test
fun `ExposedInitializer should connect to database`() {
mockkObject(Database)
every {
Database.connect(
any<DataSource>(),
any(),
any(),
any(),
any()
)
} returns mockk()
val context = SpringApplicationBuilder(CoordinatorApplication::class.java)
.properties("spring.main.web-application-type=none")
.run()
verify(exactly = 1) { Database.connect(any<DataSource>(), any(), any(), any(), any()) }
}
}

View File

@ -49,20 +49,33 @@ dependencies {
implementation(project(mapOf("path" to ":shared:common"))) implementation(project(mapOf("path" to ":shared:common")))
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("io.mockk:mockk:1.12.0")
testImplementation("com.h2database:h2:1.4.200")
testImplementation("org.assertj:assertj-core:3.4.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.2")
testImplementation("io.kotlintest:kotlintest-assertions:3.3.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
// --- Spring Boot test stack (inkluderer JUnit 5.10, Mockito, AssertJ, etc.) ---
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.mockito") // valgfritt hvis du kun bruker MockK
}
// --- MockK (Kotlin mocking) ---
testImplementation("io.mockk:mockk:1.13.8")
// --- Coroutines test utilities ---
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
// --- H2 for database testing ---
testImplementation("com.h2database:h2:2.2.224")
// --- Optional: AssertJ (Spring Boot inkluderer AssertJ, men du kan eksplisitt legge til) ---
// testImplementation("org.assertj:assertj-core:3.24.2")
// --- Optional: JUnit params (brukes ofte) ---
testImplementation("org.junit.jupiter:junit-jupiter-params")
// --- Hvis du trenger test artifacts fra shared:common ---
testImplementation(project(":shared:common", configuration = "testArtifacts"))
val exposedVersion = "0.61.0"
testImplementation("org.jetbrains.exposed:exposed-core:${exposedVersion}")
} }
tasks.test { tasks.test {

View File

@ -0,0 +1,44 @@
package no.iktdev.mediaprocessing.processer
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
import org.jetbrains.exposed.sql.Database
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension
import javax.sql.DataSource
@ExtendWith(SpringExtension::class)
@SpringBootTest(
classes = [ProcesserApplication::class],
properties = ["spring.flyway.enabled=true"]
)
class ProcesserApplicationTest {
@Test
fun `ExposedInitializer should connect to database`() {
mockkObject(Database)
every {
Database.connect(
any<DataSource>(),
any(),
any(),
any(),
any()
)
} returns mockk()
val context = SpringApplicationBuilder(ProcesserApplication::class.java)
.properties("spring.main.web-application-type=none")
.run()
verify(exactly = 1) { Database.connect(any<DataSource>(), any(), any(), any(), any()) }
}
}

View File

@ -1,8 +1,8 @@
package no.iktdev.mediaprocessing.shared.common package no.iktdev.mediaprocessing.shared.common
import mu.KotlinLogging
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.springframework.boot.ApplicationArguments import org.springframework.beans.factory.InitializingBean
import org.springframework.boot.ApplicationRunner
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.ComponentScan
@ -17,12 +17,14 @@ abstract class DatabaseApplication {
} }
} }
@Component @Component("ExposedInit")
class ExposedInitializer( class ExposedInitializer(
private val dataSource: DataSource private val dataSource: DataSource
) : ApplicationRunner { ) : InitializingBean {
private val log = KotlinLogging.logger {}
override fun run(args: ApplicationArguments?) { override fun afterPropertiesSet() {
log.info { "Starting database connection" }
Database.connect(dataSource) Database.connect(dataSource)
} }
} }