Skip to main content
Version: 6.0

Introduction to Extensions

Extensions are reusable lifecycle hooks. In fact, lifecycle hooks are themselves represented internally as instances of extensions. In the past, Kotest used the term listener for simple interfaces and extension for more advanced interfaces, however there is no distinction between the two and the terms can be used interchangeably.

Creating an Extension​

The basic usage is to create an implementation of the required extension interface and register it with a test, a spec, or project wide in ProjectConfig.

For example, here we define a BeforeSpecListener and AfterSpecListener, and register it with a spec.

class MyTestListener : BeforeSpecListener, AfterSpecListener {
override suspend fun beforeSpec(spec:Spec) {
// power up kafka
}
override suspend fun afterSpec(spec: Spec) {
// shutdown kafka
}
}


class TestSpec : FreeSpec({
extension(MyTestListener())
// tests here
})

Any extensions registered inside a Spec will be used for all tests in that spec (including test factories and nested tests).

To run an extension for every spec in the entire project, you can register the listener via project config. Here is an example of the previous MyTestListener registered at the project level so it would apply to all specs.

object ProjectConfig : AbstractProjectConfig {
override val extensions = listOf(MyTestListener())
}
caution

Some extensions can only be registered at the project level. For example, registering a BeforeProjectListener inside a spec will have no effect, since the project has already started by the time that extension would be encountered.