Reputation: 4120
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
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
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
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.
Upvotes: 0