Alex Kuznetsov
09/18/2024, 12:42 PMshouldNotThrowAny
is not compatible with assertSoftly
? I would suggest making a breaking change to its signature as follows:
inline fun <T> shouldNotThrowAny2(block: () -> T): T? {
assertionCounter.inc()
val thrownException = try {
return block()
} catch (e: Throwable) {
e
}
errorCollector.collectOrThrow(
failure(
"No exception expected, but a ${thrownException::class.simpleName} was thrown with message: \"${thrownException.message}\".",
thrownException
)
)
return null
}
so that is works inside assertSoftly, like this:
class MyTest: StringSpec() {
init {
"should not swallow exceptions, but did" {
assertSoftly {
1 shouldBe 2
shouldNotThrowAny { mimicVerifyFailure() }
}
/*
Output:
expected:<2> but was:<1>
Expected :2
Actual :1
*/
}
"should run assertions after exceptions, but did not" {
assertSoftly {
shouldNotThrowAny { mimicVerifyFailure() }
1 shouldBe 2
}
/*
Output:
No exception expected, but a AssertionError was thrown.
*/
}
"should not swallow exceptions" {
assertSoftly {
1 shouldBe 2
shouldNotThrowAny2 { mimicVerifyFailure() }
}
/* Output: The following 2 assertions failed:
1) expected:<2> but was:<1>
2) No exception expected, but a AssertionError was thrown with message: "MyService.myFunc() was never invoked".
*/
}
"should run assertions after exceptions" {
assertSoftly {
shouldNotThrowAny2 { mimicVerifyFailure() }
1 shouldBe 2
}
/* Output:
The following 2 assertions failed:
io.kotest.assertions.MultiAssertionError: The following 2 assertions failed:
1) No exception expected, but a AssertionError was thrown with message: "MyService.myFunc() was never invoked".
2) expected:<2> but was:<1>
*/
}
}
fun mimicVerifyFailure() {
throw AssertionError("MyService.myFunc() was never invoked")
}
}
I know it's a breaking change, it returns T? instead of T, but why do we need it to return anything? In my very limited experience, we need shouldNotThrowAny
only in one case, to show that a test succeeds if no exceptions were thrown, and no further assertions are needed. So we don't really need this:
val t = shouldNotThrowAny { myFunc() }
because we can just val t = myFunc()
WDYT?LeoColman
09/19/2024, 3:33 AMshouldNotThrow
was to ease assertions on unit blocks. Calling them is very close to just calling the code block itself.
I'd say the breaking changing on this guy isn't a big big issue.Alex Kuznetsov
09/19/2024, 1:01 PM