I needed to test some Kotlin code that used JDBC. I wanted an embedded SQL database for my JUnit5 tests. I’ve done this in Java a number of times so I dug into my old code and … nothing was a fit. The issues were they were very Java centric and JUnit4 based. Here’s what I rolled on my own.
JDBC Compatible Database
H2 provided an easy solution to that:
Class.forName("org.h2.Driver")
val connection = DriverManager.getConnection(
"jdbc:h2:mem:test",
"sa",
""
)!!
Kotlin and JUnit5
For Kotlin and JUnit5 I know from experience I wanted to go with implementing an @ExtendWith annotation. I also wanted test classes to have easy access to the resultant connection. Here’s what I did for that:
import org.junit.jupiter.api.extension.ExtendWith
import java.sql.Connection
@ExtendWith(EmbeddedDb::class)
open class WithConnection {
lateinit var connection: Connection
}
This allowed tests to look like:
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
class SomeTest : WithConnection() {
@Test
fun `should have a valid connection`() {
assertThat(connection).isNotNull
}
}
The meat of the work happens in the EmbeddedDb class:
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.BeforeEachCallback
import org.junit.jupiter.api.extension.ExtensionContext
import java.sql.DriverManager
class EmbeddedDb : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext) {
Class.forName("org.h2.Driver")
val connection = DriverManager.getConnection(
"jdbc:h2:mem:test",
"sa",
""
)!!
(context.requiredTestInstance as WithConnection)
.connection = connection
}
override fun afterEach(context: ExtensionContext) {
(context.requiredTestInstance as WithConnection)
.connection.close()
}
}
It’s very light weight, all it’s doing is instantiating a connection, and setting the one used by the test classes.
What You Get
With this approach, you’ll get a fresh database connection for every test method, and the connection will be set already if you add a @BeforeEach to your test class, so you can set up your schema there.