From 33ddef2bbd53f974bf169d1193dbf8c00277804a Mon Sep 17 00:00:00 2001 From: Michal Wachowski Date: Thu, 8 Aug 2024 15:11:45 +0200 Subject: [PATCH] assertions for io.strikt:strikt-core (#65) --- result4k/strikt/build.gradle.kts | 8 ++ .../forkhandles/result4k/strikt/matchers.kt | 30 +++++++ .../result4k/strikt/MatchersTest.kt | 84 +++++++++++++++++++ .../result4k/strikt/WeatherExampleKotest.kt | 40 +++++++++ 4 files changed, 162 insertions(+) create mode 100644 result4k/strikt/build.gradle.kts create mode 100644 result4k/strikt/src/main/kotlin/dev/forkhandles/result4k/strikt/matchers.kt create mode 100644 result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/MatchersTest.kt create mode 100644 result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/WeatherExampleKotest.kt diff --git a/result4k/strikt/build.gradle.kts b/result4k/strikt/build.gradle.kts new file mode 100644 index 0000000..16df84b --- /dev/null +++ b/result4k/strikt/build.gradle.kts @@ -0,0 +1,8 @@ +description = "ForkHandles Library Testing Helpers (Strikt)" + +dependencies { + implementation(project(":result4k")) + implementation("io.strikt:strikt-core:_") + + testImplementation(project(path= ":result4k", configuration= "testArtifacts")) +} diff --git a/result4k/strikt/src/main/kotlin/dev/forkhandles/result4k/strikt/matchers.kt b/result4k/strikt/src/main/kotlin/dev/forkhandles/result4k/strikt/matchers.kt new file mode 100644 index 0000000..352efd7 --- /dev/null +++ b/result4k/strikt/src/main/kotlin/dev/forkhandles/result4k/strikt/matchers.kt @@ -0,0 +1,30 @@ +package dev.forkhandles.result4k.strikt + +import dev.forkhandles.result4k.Failure +import dev.forkhandles.result4k.Success +import strikt.api.Assertion +import strikt.assertions.isA +import strikt.assertions.isEqualTo + +fun Assertion.Builder<*>.isSuccess() = + isA>() + +fun Assertion.Builder<*>.isFailure() = + isA>() + +@JvmName("isSuccessOfInstance") +inline fun Assertion.Builder<*>.isSuccess() = + isA>().and { get { value }.isA() } + +@JvmName("isFailureOfInstance") +inline fun Assertion.Builder<*>.isFailure() = + isA>().and { get { reason }.isA() } + +@JvmName("isSuccessOfInstanceAndValue") +inline fun Assertion.Builder<*>.isSuccess(expected: T) = + isA>().and { get { value }.isEqualTo(expected) } + +@JvmName("isFailureOfInstanceAndValue") +inline fun Assertion.Builder<*>.isFailure(expected: E) = + isA>().and { get { reason }.isEqualTo(expected) } + diff --git a/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/MatchersTest.kt b/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/MatchersTest.kt new file mode 100644 index 0000000..2dd16d1 --- /dev/null +++ b/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/MatchersTest.kt @@ -0,0 +1,84 @@ +package dev.forkhandles.result4k.strikt + +import dev.forkhandles.result4k.Failure +import dev.forkhandles.result4k.Success +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import strikt.api.expectThat +import strikt.api.expectThrows +import strikt.assertions.isEqualTo + +class MatchersTest { + + @Test + fun `should correctly assert when Success`() { + val actualValue = "Successful" + val actualResult = Success(actualValue) + + assertDoesNotThrow { expectThat(actualResult).isSuccess() } + assertDoesNotThrow { expectThat(actualResult).isSuccess() } + assertDoesNotThrow { expectThat(actualResult).isSuccess(actualValue) } + } + + @Test + fun `should correctly assert when Failure`() { + val actualValue = "Failed" + val actualResult = Failure(actualValue) + + assertDoesNotThrow { expectThat(actualResult).isFailure() } + assertDoesNotThrow { expectThat(actualResult).isFailure() } + assertDoesNotThrow { expectThat(actualResult).isFailure(actualValue) } + } + + @Test + fun `should correctly assert when Success but expecting Failure`() { + val actualValue = "Test successful" + val actualResult = Success(actualValue) + val expectedMessage = + "Expect that Success(value=Test successful) is an instance of dev.forkhandles.resultk.Failure found dev.forkhandles.resultk.Success" + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isFailure() + } + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isFailure() + } + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isFailure(actualValue) + } + } + + @Test + fun `should correctly assert when Failure but expecting Success`() { + val actualValue = "Test failed" + val actualResult = Failure(actualValue) + val expectedMessage = + "Expect that Failure(reason=Test failed) is an instance of dev.forkhandles.resultk.Success found dev.forkhandles.resultk.Failure" + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isSuccess() + } + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isSuccess() + } + + expectAssertionError(expectedMessage) { + expectThat(actualResult).isSuccess(actualValue) + } + } + + private fun expectAssertionError(message: String, block: () -> Unit) = + expectThrows { block() } + .and { get { subject.formatterMessage }.isEqualTo(message) } + + private val AssertionError.formatterMessage + get() = + message + ?.replace("[^\\p{L}.()\\[\\] =]+".toRegex(), "") + ?.replace(" +".toRegex(), " ") + ?.trim() + .also { println(it) } +} diff --git a/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/WeatherExampleKotest.kt b/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/WeatherExampleKotest.kt new file mode 100644 index 0000000..90d60a8 --- /dev/null +++ b/result4k/strikt/src/test/kotlin/dev/forkhandles/result4k/strikt/WeatherExampleKotest.kt @@ -0,0 +1,40 @@ +package dev.forkhandles.result4k.strikt + +import dev.forkhandles.result4k.Weather +import dev.forkhandles.result4k.WeatherError +import dev.forkhandles.result4k.getWeather +import org.junit.jupiter.api.Test +import strikt.api.expectThat +import java.math.BigDecimal + +class WeatherExampleKotest { + @Test + fun `assert any success`() { + expectThat(getWeather(20)).isSuccess() + } + + @Test + fun `assert type success`() { + expectThat(getWeather(20)).isSuccess() + } + + @Test + fun `assert exact success`() { + expectThat(getWeather(20)).isSuccess(Weather(BigDecimal("295.15"), 101_390)) + } + + @Test + fun `assert any failure`() { + expectThat(getWeather(9001)).isFailure() + } + + @Test + fun `assert type failure`() { + expectThat(getWeather(9001)).isFailure() + } + + @Test + fun `assert exact failure`() { + expectThat(getWeather(9001)).isFailure(WeatherError(404, "unsupported location")) + } +}