Kotest Arrow extensions 1.3.0 is now available
by Imran Settuba
- •
- November 21, 2022
- •
- arrow• kotlin• functional programming• testing
- |
- 5 minutes to read.

Kotest Arrow extension libraries releases version 1.3.0, adding a new multiplatform arrow-fx-coroutines assertion module
complementing kotest-assertions-arrow
with combinators for Arrow Fx.
Thanks for all the feedback and contributions!
Table of Contents
Setting up Kotest Assertion for Arrow Fx
The Gradle setup is fairly straightforward:
dependencies {
implementation("io.arrow-kt:arrow-fx-coroutines:arrow_version") // assuming this is not in the project classpath
testImplementation("io.kotest.extensions:kotest-assertions-arrow-fx-coroutines:1.3.0")
}
It applies similarly in Maven:
<dependency>
<groupId>io.kotest.extensions</groupId>
<artifactId>kotest-assertions-arrow-fx-coroutines-jvm</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>
Try out our various templates for a fast and easy set-up.
Resource combinators
Combinators for Resource simplify integration tests or testing various kinds of dependencies.
Including smart-casted assertions:
- Resource#shouldBeResource
class ResourceSpec : StringSpec({
"Int Resources are the same" {
checkAll(Arb.int()) { n ->
val b: Int = Resource.just(n).shouldBeResource(n)
b shouldBe n
}
}
})
or comparing different Resource results like here:
"resource equality" {
checkAll(Arb.int()) { n ->
val a = Resource({ n }, { _, _ -> Unit })
val b = Resource({ n }, { nn, _ -> println("release $nn") })
a.shouldBeResource(b) shouldBe n
}
}
Safely consume Resources
A key extension function to consume Resources safely - without Resource violations - in any Kotest [Spec] is Resource#extension
.
See an example of Hikari and Exposed below.
fun hikari(config: HikariConfig): Resource<DataSource> =
Resource.fromCloseable { HikariDataSource(config) }
fun database(ds: DataSource): Resource<Database> =
Resource(
acquire = { Database.connect(ds) },
release = { db, _: ExitCase -> closeAndUnregister(db) }
)
class DependencyGraph(val database: Database)
fun dependencies(config: HikariConfig): Resource<DependencyGraph> =
resource {
val ds = hikari(config).bind()
val db = database(ds).bind()
DependencyGraph(db)
}
In a Kotest [Spec], we can safely consume the database with Kotest [MountableExtension] using [install]:
import io.kotest.core.extensions.install
import io.kotest.assertions.arrow.fx.coroutines.extension
class DatabaseSpec : StringSpec({
val config = HikariConfig().apply {
// add config settings
}
val dependencyGraph: DependencyGraph = install(dependencies(config).extension())
// follow up with tests
"test" {
val database: Database = dependencyGraph.get().database
}
})
There is an option to register [Resource] on a Project wide configuration with [ProjectResource] which interoperates with Kotest [Extension].
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.assertions.arrow.fx.coroutines.ProjectResource
object ProjectConfig: AbstractProjectConfig() {
val config = HikariConfig().apply {
// add config settings
}
val dependencyGraph: ProjectResource<DependencyGraph> =
ProjectResource(dependencies(config))
override fun extensions(): List<Extension> = listOf(dependencyGraph)
}
class MySpec : StringSpec({
"test project wide database" {
val database: Database = ProjectConfig.dependencyGraph.get().database
}
})
ExitCase
The library contains smart-casted operators for ExitCase like ExitCase#shouldBeCompleted
, among others:
import kotlinx.coroutines.CompletableDeferred
import io.kotest.assertions.arrow.fx.coroutines.resource
import io.kotest.assertions.arrow.fx.coroutines.shouldBeCompleted
import arrow.fx.coroutines.ExitCase
import arrow.core.identity
class ExitCaseSpec: StringSpec({
"value resource is released with Completed" {
checkAll(Arb.int()) { n: Int ->
val completable = CompletableDeferred<ExitCase>()
val nn: Int = Resource({ n }, { _, ex -> completable.complete(ex) }).use(::identity)
nn shouldBe n
completable.await().shouldBeCompleted()
}
}
"shouldBeCancelled(e)" {
checkAll(Arb.string().map { CancellationException(it) }) { e ->
ExitCase.Cancelled(e).shouldBeCancelled(e)
}
}
})
There will be a follow-up blog post with more in-depth content on using Kotest Arrow extension libraries.