Skip to content
This repository has been archived by the owner on Feb 2, 2025. It is now read-only.

Commit

Permalink
Add Raise matchers (#262)
Browse files Browse the repository at this point in the history
Co-authored-by: Tim Grafford <[email protected]>
  • Loading branch information
tgrafford and Tim Grafford authored May 25, 2024
1 parent 3620ba8 commit 194a47e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.kotest.assertions.arrow.core

import arrow.core.raise.Raise
import arrow.core.raise.recover
import io.kotest.assertions.failure
import io.kotest.assertions.print.print

/**
* Verifies if a block of code will raise a specified type of [T] (or subclasses).
*
* This function will include subclasses of [T]. For example, if you test for [CharSequence] and the code raises
* [String], the test will pass.
*
* ```kotlin
* val raised: String = shouldRaise<String> {
* raise("failed")
* }
* ```
*/
public suspend inline fun <reified T> shouldRaise(noinline block: suspend Raise<Any?>.() -> Any?): T {
val expectedRaiseClass = T::class
return recover({
block()
throw failure("Expected to raise ${expectedRaiseClass.simpleName} but nothing was raised.")
}) { raised ->
when (raised) {
is T -> raised
null -> throw failure("Expected to raise ${expectedRaiseClass.simpleName} but <null> was raised instead.")
else -> throw failure("Expected to raise ${expectedRaiseClass.simpleName} but ${raised::class.simpleName} was raised instead.")
}
}
}

/**
* Verifies that a block of code will not raise anything.
*
* ```kotlin
* val raised: String = shouldNotRaise {
* raise("failed") // fails
* }
* ```
*/
public suspend fun <T> shouldNotRaise(block: suspend Raise<Any?>.() -> T): T {
return recover({
block()
}) { raised ->
throw failure("No raise expected, but ${raised.print().value} was raised.")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.kotest.assertions.arrow.core

import io.kotest.assertions.arrow.shouldBe
import io.kotest.assertions.throwables.shouldThrowWithMessage
import io.kotest.core.spec.style.StringSpec

class RaiseMatchers : StringSpec({
"shouldRaise: specific type" {
val raised = shouldRaise<String> {
raise("failed")
}
raised shouldBe "failed"
}

"shouldRaise: subtype" {
val raised = shouldRaise<CharSequence> {
raise("failed")
}
raised shouldBe "failed"
}

"shouldRaise: nullable type" {
val raised = shouldRaise<String?> {
raise(null)
}
raised shouldBe null
}

"shouldRaise: fail if null is raised when not expected" {
shouldThrowWithMessage<AssertionError>("Expected to raise String but <null> was raised instead.") {
shouldRaise<String> {
raise(null)
}
}
}

"shouldRaise: fail if expected raise type differs from actual" {
shouldThrowWithMessage<AssertionError>("Expected to raise Int but String was raised instead.") {
shouldRaise<Int> {
raise("failed")
}
}
}

"shouldRaise: fail if nothing is raised" {
shouldThrowWithMessage<AssertionError>("Expected to raise Int but nothing was raised.") {
shouldRaise<Int> {
42
}
}
}

"shouldNotRaise" {
val res = shouldNotRaise {
42
}
res shouldBe 42
}

"shouldNotRaise: fail if something is raised" {
shouldThrowWithMessage<AssertionError>("No raise expected, but \"failed\" was raised.") {
shouldNotRaise {
raise("failed")
}
}
}

"shouldNotRaise: fail if null was raised" {
shouldThrowWithMessage<AssertionError>("No raise expected, but <null> was raised.") {
shouldNotRaise {
raise(null)
}
}
}
})

0 comments on commit 194a47e

Please sign in to comment.