c-an
c-an

Reputation: 4120

What does relaxed = true do in mockK?

I read document, but I don't still get it.

The differences between this

private val myClass: MyClass = mockk(relaxed = true)

and this.

private val myClass: MyClass = mockk()

What I understood is if relaxed is true. Then, all the member fields or methods will return default values. Otherwise, not. is that correct understanding?

If so, setting always relaxed = true is better. But In this video, Ryan uses both. why?

https://youtu.be/60KFJTb_HwU?t=1015

Upvotes: 23

Views: 22383

Answers (3)

dkb
dkb

Reputation: 4596

Sample code: with kotest + Mockk.
Please read inline comments with code.

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.mockk.MockKException
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify

/**
 * Interface with
 * one attribute
 * one method with non-unit return value(does return something)
 * one method with no return type i.e. Unit type(does not return anything)
 *
 */
interface Navigator {
  val currentLocation: String

  fun navigateTo(newLocation: String): String

  fun systemCheck(exclusions: List<String>): Unit
}

class MockkRelaxUsageTest : FunSpec({

  test("navigator") {
    val navigator = mockk<Navigator>()
    every { navigator.currentLocation } returns "Home"

    // prints "Home"
    println(navigator.currentLocation)
    // throws an error
    navigator.navigateTo("Store")
  }

  test("relaxed navigator") {
    val navigator = mockk<Navigator>(relaxed = true)
    every { navigator.currentLocation } returns "Home"

    // prints "Home"
    println(navigator.currentLocation)
    // throws an error
    navigator.navigateTo("Store")
  }

  test("relaxedUnitFun navigator") {
    val navigator = mockk<Navigator>(relaxUnitFun = true)
    every { navigator.currentLocation } returns "Home"

    println(navigator.currentLocation) // prints "Home"

    // I just wrapped under shouldThrow assertions instead of commenting this code.
    // But you get the idea that if relaxUnitFun = true then mockk will not mock methods which returns non unit type.
    val mockKException = shouldThrow<MockKException> {
      navigator.navigateTo("Store") // throws an mockKException
    }

    println(mockKException.message) // no answer found for Navigator(#2).navigateTo(Store) among the configured answers: (Navigator(#2).getCurrentLocation()))

    val exclusionList = listOf("a", "b")
    println(navigator.systemCheck(exclusionList))

    verify(exactly = 1) { navigator.systemCheck(exclusionList) }
  }
})

Ref:

Upvotes: 0

Mieszko Koźma
Mieszko Koźma

Reputation: 634

If you're trying to call a mock method that doesn't know what to return and relaxed is not set to true you'll get an exception thrown. This is made, so tests are less likely to introduce unpredictable behavior, due to the default values returned by methods that the developer does not purposely mock.

In the linked video the view methods are probably never called, therefore no "relaxed" is necessary. You can also use "relaxedUnitFun", which works only for methods returning Unit, handy for example for classes responsible for events logging.

This is a double-edged weapon though, as "relaxing" everything deprives you of the security mechanism mentioned above. If this is what you want, you can also configure this globally, check https://mockk.io/#settings-file

Upvotes: 14

Martin Marconcini
Martin Marconcini

Reputation: 27246

To quote their documentation:

A relaxed mock is the mock that returns some simple value for all functions. This allows you to skip specifying behavior for each case, while still stubbing things you need. For reference types, chained mocks are returned.

source

Upvotes: 0

Related Questions