Skip to content

spoptchev/kotlin-preconditions

Repository files navigation

Kotlin Preconditions Build Status

kotlin-preconditions will assist you in ensuring all of your invariants are met before an operation is executed.

Usage

kotlin-preconditions provides a powerful DSL for defining preconditions:

checkThat(1) { isLt(2) }
checkThat(listOf(1, 2)) { contains(1) }

requireThat(1) { isLt(2) }
requireThat(listOf(1, 2)) { contains(1) }

If any of the preconditions are not met then checkThat will throw an IllegalStateException and requireThat will throw an IllegalArgumentException. The exception message will be generated lazily, so your application does not waste resources on evaluating objects that may not trigger an exception.

Compose your preconditions the way you like it:

val list = listOf(1, 2)

requireThat(list) { contains(3) or contains(1) and not(hasSize(3)) }

// nested preconditions
val text: String? = "hello"

requireThat(text) {
    not(isNull()) and {
        hasLength(6) or { startsWith("he") and endsWith("llo") }
    }
}

API Overview

Aliases

Instead of checkThat and requireThat you can also use check and require.

val value = "hello"

check(value) { startsWith("he") and hasLength(5) and not(includes("io")) }
require(value) { startsWith("he") and hasLength(5) and not(includes("io")) }

String preconditions

val value = "hello"

requireThat(value) { startsWith("he") and hasLength(5) and not(includes("io")) }
requireThat(value) { includes("ll") }
requireThat(value) { matches("hello") }
requireThat(value) { endsWith("lo") }
requireThat(value) { hasLength(5) }
requireThat(value) { not(isBlank()) }
requireThat(value) { not(isEmpty()) }
requireThat(value) { hasLengthBetween(1, 5) }

Collection preconditions

val list = listOf(1, 2)

requireThat(list) { hasSize(2) }
requireThat(list) { contains(1) or contains(3) and not(hasSize(3)) }
requireThat(list) { containsAll(1, 2) }
requireThat(list) { containsAll(list) }
requireThat(list) { isSorted() }

Comparable preconditions

requireThat(1) { isLt(2) }
requireThat(1) { isLte(1) }
requireThat(1) { isGt(0) }
requireThat(1) { isGte(1) }
requireThat(1) { isBetween(0..2) }

Map preconditions

val map = mapOf(1 to "1")

requireThat(map) { hasKey(1) }
requireThat(map) { hasValue("1") }
requireThat(map) { contains(1, "1") }

Object preconditions

val result = Result(true)

requireThat(result) { not(isNull()) }
requireThat(result) { isEqualTo(result) }
requireThat(result) { isSameInstanceAs(result) }

Composed preconditions

val value = "hello"

requireThat(value) { startsWith("he") and hasLength(5) and not(includes("io")) }

Labels

val numbers = listOf(1, 2)

requireThat(numbers, "Numbers") { contains(3) or contains(1) and not(hasSize(3)) }

Custom matchers

Custom matchers can be added by using extension functions:

data class Car(val age: Int)

fun PreconditionBlock<Car>.hasAge(expected: Int) = object : Matcher<Car>() {
    override fun test(condition: Condition<Car>) = condition.test {
        withResult(value.age == expected) { "expected car to be $expected years old, but was ${value.age}" }
    }
}

requireThat(Car(22)) { hasAge(22) }

Installation

Maven:

<dependency>
  <groupId>com.github.spoptchev</groupId>
  <artifactId>kotlin-preconditions</artifactId>
  <version>6.1.0</version>
</dependency>

Gradle:

compile 'com.github.spoptchev:kotlin-preconditions:6.1.0'

About

Precondition error checking for Kotlin

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages