Best Kotest code snippet using io.kotest.core.extensions.MountableExtension.Spec.install
JdbcTestContainerExtension.kt
Source:JdbcTestContainerExtension.kt
1package io.kotest.extensions.testcontainers2import com.zaxxer.hikari.HikariDataSource3import io.kotest.core.extensions.MountableExtension4import io.kotest.core.listeners.AfterSpecListener5import io.kotest.core.listeners.TestListener6import io.kotest.core.spec.Spec7import io.kotest.core.test.TestCase8import io.kotest.core.test.TestResult9import io.kotest.core.test.TestType10import io.kotest.core.test.isRootTest11import kotlinx.coroutines.Dispatchers12import kotlinx.coroutines.withContext13import org.testcontainers.containers.JdbcDatabaseContainer14import java.io.PrintWriter15import java.sql.Connection16import java.util.logging.Logger17import javax.sql.DataSource18/**19 * A Kotest [MountableExtension] for [JdbcDatabaseContainer]s that will launch the container20 * upon install, and close after the spec has completed.21 *22 * This extension will create a pooled [HikariDataSource] attached to the database and23 * return that to the user as the materialized value.24 *25 * The pool can be configured in the mount configure method.26 *27 * Note: This extension requires Kotest 5.0+28 *29 * @param container the specific test container type30 * @param lifecycleMode determines how the container should be reset between tests31 *32 * @since 1.1.033 */34class JdbcTestContainerExtension(35 private val container: JdbcDatabaseContainer<Nothing>,36 private val lifecycleMode: LifecycleMode = LifecycleMode.Spec,37) : MountableExtension<TestContainerHikariConfig, DataSource>, AfterSpecListener, TestListener {38 private val ds = SettableDataSource(null)39 private var configure: TestContainerHikariConfig.() -> Unit = {}40 override fun mount(configure: TestContainerHikariConfig.() -> Unit): DataSource {41 this.configure = configure42 if (lifecycleMode == LifecycleMode.Spec) {43 container.start()44 ds.setDataSource(createDataSource())45 }46 return ds47 }48 private fun createDataSource(): HikariDataSource {49 val config = TestContainerHikariConfig()50 config.jdbcUrl = container.jdbcUrl51 config.username = container.username52 config.password = container.password53 config.configure()54 val ds = HikariDataSource(config)55 runInitScripts(ds.connection, config.dbInitScripts)56 return ds57 }58 override suspend fun afterSpec(spec: Spec) {59 withContext(Dispatchers.IO) {60 stop()61 }62 }63 override suspend fun beforeAny(testCase: TestCase) {64 val every = lifecycleMode == LifecycleMode.EveryTest65 val root = lifecycleMode == LifecycleMode.Root && testCase.isRootTest()66 val leaf = lifecycleMode == LifecycleMode.Leaf && testCase.type == TestType.Test67 if (every || root || leaf) {68 start()69 }70 }71 override suspend fun afterAny(testCase: TestCase, result: TestResult) {72 val every = lifecycleMode == LifecycleMode.EveryTest73 val root = lifecycleMode == LifecycleMode.Root && testCase.isRootTest()74 val leaf = lifecycleMode == LifecycleMode.Leaf && testCase.type == TestType.Test75 if (every || root || leaf) {76 stop()77 }78 }79 private suspend fun start() {80 withContext(Dispatchers.IO) {81 container.start()82 ds.setDataSource(createDataSource())83 }84 }85 private suspend fun stop() {86 withContext(Dispatchers.IO) {87 ds.setDataSource(null)88 container.stop()89 }90 }91 private fun runInitScripts(connection: Connection, dbInitScripts: List<String>) {92 val scriptRunner = ScriptRunner(connection)93 if (dbInitScripts.isNotEmpty()) {94 dbInitScripts.forEach {95 val resourceList = ResourceLoader().resolveResource(it)96 resourceList97 .filter { resource -> resource.endsWith(".sql") }98 .forEach { resource ->99 scriptRunner.runScript(resource.loadToReader())100 }101 }102 }103 }104}105class SettableDataSource(private var ds: HikariDataSource?) : DataSource {106 private fun getDs(): DataSource = ds ?: error("DataSource is not ready")107 fun setDataSource(ds: HikariDataSource?) {108 this.ds?.close()109 this.ds = ds110 }111 override fun getLogWriter(): PrintWriter {112 return getDs().logWriter113 }114 override fun setLogWriter(out: PrintWriter?) {115 getDs().logWriter = out116 }117 override fun setLoginTimeout(seconds: Int) {118 getDs().loginTimeout = seconds119 }120 override fun getLoginTimeout(): Int {121 return getDs().loginTimeout122 }123 override fun getParentLogger(): Logger {124 return getDs().parentLogger125 }126 override fun <T : Any?> unwrap(iface: Class<T>?): T {127 return getDs().unwrap(iface)128 }129 override fun isWrapperFor(iface: Class<*>?): Boolean {130 return getDs().isWrapperFor(iface)131 }132 override fun getConnection(): Connection {133 return getDs().connection134 }135 override fun getConnection(username: String?, password: String?): Connection {136 return getDs().getConnection(username, password)137 }138}...
SharedJdbcDatabaseContainerExtension.kt
Source:SharedJdbcDatabaseContainerExtension.kt
1package io.kotest.extensions.testcontainers2import com.zaxxer.hikari.HikariConfig3import com.zaxxer.hikari.HikariDataSource4import io.kotest.core.extensions.MountableExtension5import io.kotest.core.listeners.AfterProjectListener6import io.kotest.core.listeners.AfterSpecListener7import io.kotest.core.listeners.AfterTestListener8import io.kotest.core.listeners.BeforeSpecListener9import io.kotest.core.listeners.BeforeTestListener10import io.kotest.core.spec.Spec11import io.kotest.core.test.TestCase12import io.kotest.core.test.TestResult13import org.testcontainers.containers.JdbcDatabaseContainer14import java.sql.Connection15/**16 * A Kotest [MountableExtension] for [JdbcDatabaseContainer]s that are started the first time they are17 * installed in a test, and then shared throughout the same gradle module. The container is shutdown18 * after all specs have completed.19 *20 * If no spec is executed that installs a particular container, then that container is never started.21 *22 * This extension will create a pooled [HikariDataSource] attached to the database and23 * return that to the user as the materialized value.24 *25 * The Hikari pool can be configured in the constructor through the [configure] parameter, or through26 * the install method per spec. If the latter option is used, then only the configure function from27 * the install where the container is first started will be executed.28 *29 * Note: This extension requires Kotest 5.0+30 *31 * @param container the specific database test container type32 * @param beforeSpec a beforeSpec callback33 * @param afterSpec an afterSpec callback34 * @param beforeTest a beforeTest callback35 * @param afterTest a afterTest callback36 * @param afterStart called one time, after the container is started37 * @param configure a callback to configure the [HikariConfig] instance that is used to create the [HikariDataSource].38 *39 * @since 1.3.040 */41class SharedJdbcDatabaseContainerExtension(42 private val container: JdbcDatabaseContainer<*>,43 private val beforeTest: suspend (HikariDataSource) -> Unit = {},44 private val afterTest: suspend (HikariDataSource) -> Unit = {},45 private val beforeSpec: suspend (HikariDataSource) -> Unit = {},46 private val afterSpec: suspend (HikariDataSource) -> Unit = {},47 private val afterStart: (HikariDataSource) -> Unit = {},48 private val configure: TestContainerHikariConfig.() -> Unit = {},49) : MountableExtension<TestContainerHikariConfig, HikariDataSource>,50 AfterProjectListener,51 BeforeTestListener,52 BeforeSpecListener,53 AfterTestListener,54 AfterSpecListener {55 private var ds: HikariDataSource? = null56 override fun mount(configure: TestContainerHikariConfig.() -> Unit): HikariDataSource {57 if (!container.isRunning) {58 container.start()59 ds = createDataSource().apply(afterStart)60 }61 return ds ?: error("DataSource was not initialized")62 }63 override suspend fun afterProject() {64 if (container.isRunning) container.stop()65 }66 override suspend fun beforeTest(testCase: TestCase) {67 beforeTest(ds ?: error("DataSource was not initialized"))68 }69 override suspend fun afterTest(testCase: TestCase, result: TestResult) {70 afterTest(ds ?: error("DataSource was not initialized"))71 }72 override suspend fun beforeSpec(spec: Spec) {73 beforeSpec(ds ?: error("DataSource was not initialized"))74 }75 override suspend fun afterSpec(spec: Spec) {76 afterSpec(ds ?: error("DataSource was not initialized"))77 }78 private fun runInitScripts(connection: Connection, dbInitScripts: List<String>) {79 if (dbInitScripts.isNotEmpty()) {80 val scriptRunner = ScriptRunner(connection)81 dbInitScripts.forEach { script ->82 ResourceLoader()83 .resolveResource(script)84 .filter { it.endsWith(".sql") }85 .forEach { scriptRunner.runScript(it.loadToReader()) }86 }87 }88 }89 private fun createDataSource(): HikariDataSource {90 val config = TestContainerHikariConfig()91 config.jdbcUrl = container.jdbcUrl92 config.username = container.username93 config.password = container.password94 config.configure()95 val ds = HikariDataSource(config)96 runInitScripts(ds.connection, config.dbInitScripts)97 return ds98 }99}...
MountableExtensionTest.kt
Source:MountableExtensionTest.kt
1package com.sksamuel.kotest.engine.extensions2import io.kotest.core.extensions.MountableExtension3import io.kotest.core.extensions.install4import io.kotest.core.listeners.BeforeSpecListener5import io.kotest.core.spec.Spec6import io.kotest.core.spec.style.FunSpec7import io.kotest.matchers.shouldBe8import java.util.concurrent.atomic.AtomicBoolean9class MountableExtensionTest : FunSpec() {10 private val mountable = MyMountable()11 private val control = install(mountable) {12 a = "bar"13 }14 init {15 test("mountable extensions should invoke configuration block") {16 control.a shouldBe "bar"17 }18 test("mountable extensions should be installed as regular extensions") {19 mountable.before.get() shouldBe true20 }21 }22}23data class Config(var a: String)24class MyMountable : MountableExtension<Config, Config>, BeforeSpecListener {25 val before = AtomicBoolean(false)26 override suspend fun beforeSpec(spec: Spec) {27 before.set(true)28 }29 override fun mount(configure: (Config) -> Unit): Config {30 val config = Config("foo")31 configure(config)32 return config33 }34}...
MountableExtension.kt
Source:MountableExtension.kt
1package io.kotest.core.extensions2import io.kotest.core.spec.Spec3/**4 * A [MountableExtension] is an [Extension] that can return a materialized value to the5 * user and allows for a configuration block.6 *7 * This allows extensions to return control objects which differ from the extension itself.8 *9 * For example:10 *11 * class MyTest : FunSpec() {12 * init {13 * val kafka = install(EmbeddedKafka) {14 * port = 909215 * }16 * }17 * }18 *19 * Here `kafka` is a materialized value that contains details of the host/port of the20 * started kafka instance and `EmbeddedKafka` is the extension itself.21 *22 */23interface MountableExtension<CONFIG, MATERIALIZED> : Extension {24 // cannot be suspending as it is invoked by install that is used in constructors25 fun mount(configure: CONFIG.() -> Unit): MATERIALIZED26}27// cannot be suspending as it is used in constructors28fun <CONFIG, MATERIALIZED> Spec.install(29 mountable: MountableExtension<CONFIG, MATERIALIZED>,30 configure: CONFIG.() -> Unit = {}31): MATERIALIZED {32 extensions(mountable)33 return mountable.mount(configure)34}...
Spec.install
Using AI Code Generation
1 Spec.install(Extension1())2 Spec.install(Extension2())3 Spec.install(Extension3())4 Spec.install(Extension4())5 Spec.install(Extension5())6 Spec.install(Extension6())7 Spec.install(Extension7())8 Spec.install(Extension8())9 Spec.install(Extension9())10 Spec.install(Extension10())11 Spec.install(Extension11())12 Spec.install(Extension12())13 Spec.install(Extension13())14 Spec.install(Extension14())15 Spec.install(Extension15())16 Spec.install(Extension16())17 Spec.install(Extension17())18 Spec.install(Extension18())19 Spec.install(Extension19())20 Spec.install(Extension20())21 Spec.install(Extension21())22 Spec.install(Extension22())23 Spec.install(Extension23())24 Spec.install(Extension24())25 Spec.install(Extension25())26 Spec.install(Extension26())27 Spec.install(Extension27())28 Spec.install(Extension28())29 Spec.install(Extension29())30 Spec.install(Extension30())31 Spec.install(Extension31())32 Spec.install(Extension32())33 Spec.install(Extension33())34 Spec.install(Extension34())35 Spec.install(Extension35())36 Spec.install(Extension36())37 Spec.install(Extension37())38 Spec.install(Extension38())39 Spec.install(Extension39())40 Spec.install(Extension40())41 Spec.install(Extension41())42 Spec.install(Extension42())43 Spec.install(Extension43())44 Spec.install(Extension44())45 Spec.install(Extension45())46 Spec.install(Extension46())47 Spec.install(Extension47())48 Spec.install(Extension48())49 Spec.install(Extension49())50 Spec.install(Extension50())51 Spec.install(Extension51())52 Spec.install(Extension52())53 Spec.install(Extension53())54 Spec.install(Extension54())55 Spec.install(Extension55())56 Spec.install(Extension56())57 Spec.install(Extension57())58 Spec.install(Extension58())59 Spec.install(Extension59())60 Spec.install(Extension60())61 Spec.install(Extension61())62 Spec.install(Extension62())63 Spec.install(Extension63())64 Spec.install(Extension64())65 Spec.install(Extension65())66 Spec.install(Extension66())67 Spec.install(Extension67())68 Spec.install(Extension68())69 Spec.install(Extension69())70 Spec.install(Extension70
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!