is there a way to avoid this compiler error in a f...
# getting-started
m
is there a way to avoid this compiler error in a function that has a return type?
acraWrapper.logAndThrow()
logs some exception information and then just rethrows the exception outside of just tricking it by returning an invalid value, that is
p
Making return type of
logAndThrow
be
Nothing
should help, if I understood you correctly.
m
huh, i’ve not seen that type before. that works though. thanks
👍 1
hmm, the problem with that is it looks like stubbing a function with a
Nothing
return type causes the rest of the test to be unreachable
guess i’ll just return garbage values
k
Well yes, a function that returns
Nothing
can never return and so everything after that is unreachable, isn't that what you want?
m
in the normal case, sure. but then i’m not sure how to test that behavior. eg:
Copy code
fun doThing() {
    try { thing() }
    catch (err: Exception) {
        acraWrapper.logAndThrow(err)
    }
}

@Test(expected = Exception::class)
fun testDoThing() {
    whenever(mockAcraWrapper.logAndThrow(any())
        .thenThrow(Exception())

    doThing()
}
anything after the stub becomes unreachable
k
What do you want the mock
logAndThrow
call to do?
m
throw an exception, like it would in a normal use case
k
Okay so you call
logAndThrow
, it always throws and
.thenThrow()
and
doThing()
never even happen, and that's what the compiler is warning about.
m
but
logAndThrow
shouldn’t be called until
doThing()
is called and the subsequent call to
thing()
fails
k
What magical thing does
whenever
do that causes the first line of
testDoThing
to not simply call
logAndThrow
?
m
i guess i don’t really know?
whenever
is just a wrapper for mockito’s
when
function, which is a keyword in kotlin
my assumption was it delayed execution until the call on the mock
k
That can't be the case, a function can't delay evaluating its arguments, that's not how Kotlin works. The compiler warning about unreachable code is correct here.
p
I guess the magic is not in
whenever
but in
mockAcraWrapper
instance which is mocked, so it actually does not call original
logAndThrow
method. I didn’t work with mocking much, so I can’t help. But do not “return garbage values”. For instance, you can call
error()
function after
acraWrapper.logAndThrow(err)
. This would be more explicit.
Copy code
fun doThing() {
    try { thing() }
    catch (err: Exception) {
        acraWrapper.logAndThrow(err)
        error("should not happen")
    }
}
m
okay, thanks for the suggestion