I am not sure if this is possible or if there's a better architecture for this. I wrote a function that does some tests:
fun validate(a: Any?, b: Any?){
a shouldBe b
}
My function is obviously more complex than that, but now I would like to test the test itself. For example, I want to pass a=1
and b=null
and make sure it fails. Is there a way to test for it to fail or succeed using Kotest
?
If not, what is a proper way to architect this?
I am trying to rely on this test often and in many places of my service, so I would like it to be as reliable as possible.
Short answer: use shouldFail { ... }
.
This is possible because failing tests in Kotest (and many other frameworks) will throw an AssertionError
. You can check for that exception to see whether the test failed. So to check for a failed assertion, you can write:
shouldThrow<AssertionError> { /* your failing test here */ }
As you'd probably expect, shouldThrow
will catch the exception so that it doesn't propagate. So in effect it will turn a failing test into a passing test, and vice versa.
To make it a bit more convenient and readable, you could write a couple of extension functions, like this:
fun shouldFail(block: () -> Unit) = shouldThrow<AssertionError>(block)
fun shouldNotFail(block: () -> Unit) = shouldNotThrow<AssertionError>(block)
In fact Kotest includes the shouldFail
function in the standard assertions, so you don't even need to define it yourself. Their implementation is the same as what I have suggested here. They don't include a shouldNotFail
, though, presumably because the usefulness is a bit questionable. Wrapping a test in "shouldNotFail" makes it fail if the assertion fails and pass if the assertion passes, which is... exactly what it would have done if you didn't wrap it in anything at all.
To test your own assertion functions, you can use it like this:
shouldFail { 1 shouldBe 2 }
If you look at the source code for Kotest itself, you'll find many unit tests for the built-in assertion functions using exactly this approach.