kotlinmockk

mockk every {}.throws() Exception fails test


I need to verify that a certain call is not made, when a previous method call throws an Exception.

    // GIVEN
    every { relaxedMock.eats() }.throws(NotHungryException())
    
    // WHEN
    sut.live()
    
    // THEN
    verify (exactly = 0) { relaxedMock2.sleeps() }

Problem with this code, it fails because of the Exception thrown and not because of the failed verification.


Solution

  • I understand that your WHEN block will always throw an exception. In that case you have multiple options from my point of view:

    1. Simple plain Kotlin. Wrap the WHEN block with a try-catch block, e.g. like this:
    // GIVEN
    every { relaxedMock.eats() }.throws(NotHungryException())
        
    // WHEN
    var exceptionThrown: Boolean = false
    try {
        sut.live()
    } catch(exception: NotHungryException) {
        // Maybe put some assertions on the exception here.
        exceptionThrown = true
    }
    assertTrue(exceptionThrown)
        
    // THEN
    verify (exactly = 0) { relaxedMock2.sleeps() }
    
    1. For a bit nicer code, you can use JUnit5 API's Assertions. assertThrows will expect an exception being thrown by a specific piece of code. It will fail the test, if no exception is thrown. Also it will return the thrown exception, for you to inspect it.
    import org.junit.jupiter.api.Assertions
    
    // GIVEN
    every { relaxedMock.eats() }.throws(NotHungryException())
        
    // WHEN
    val exception = Assertions.assertThrows(NotHungryException::class.java) { sut.live() }
        
    // THEN
    verify (exactly = 0) { relaxedMock2.sleeps() }
    
    1. If you're using Kotest you can use the shouldThrow assertion. Which also allows you to retrieve the thrown exception and validate its type.
    import io.kotest.assertions.throwables.shouldThrow
    
    // GIVEN
    every { relaxedMock.eats() }.throws(NotHungryException())
        
    // WHEN
    val exception = shouldThrow<NotHungryException> { sut.live() }
        
    // THEN
    verify (exactly = 0) { relaxedMock2.sleeps() }