Verify that functions were called

When using mocked dependencies, you usually want to test that your code calls the correct functions. In MockK, this is accomplished using the verify function.

Using verify to verify that a function was called looks a lot like using every for stubbing. A simple example is to call a method and immediately check that it was called.

  1. import io.mockk.every
  2. import io.mockk.mockk
  3. import io.mockk.verify
  4. val navigator = mockk<Navigator>()
  5. every { navigator.navigateTo(any()) } returns Unit
  6. navigator.navigateTo("Park")
  7. verify { navigator.navigateTo("Park") }

Similar to stubbing with every, verify starts a verification block and uses anonymous functions and infix functions to define what will be verified. verify supports the same argument matchers as every, along with a few additional matchers.

Inside the verification block (between the opening curly bracket { and closing curly bracket }), you write the method you want to verify. { navigator.navigateTo("Park") } tells MockK to check if the navigateTo method on the navigator object was called with the argument "Park".

Verifying dependencies

In the previous simple example, verification isn’t very helpful as it just checks that the previous line ran. Verification becomes more useful when you are testing other classes, that depend on mocked instances. Let’s start testing a button.

  1. class Button {
  2. private var clickListener: (() -> Unit)? = null
  3. fun setOnClickListener(listener: () -> Unit) {
  4. clickListener = listener
  5. }
  6. fun performClick() {
  7. clickListener?.invoke()
  8. }
  9. }
  10. class NavigationView(
  11. private val navigator: Navigator
  12. ) {
  13. val goToParkButton = Button()
  14. init {
  15. goToParkButton.setOnClickListener {
  16. navigator.navigate("Park")
  17. }
  18. }
  19. }

A test for the above NavigationView class should check that clicking the goToParkButton tells the navigator to go to the park. If the navigator doesn’t record where it goes, then it can be difficult to check that the button does its job correctly. This is a scenario where MockK can shine.

  1. // Mock the dependency needed for navigationView
  2. val navigator = mockk<Navigator>()
  3. every { navigator.navigateTo(any()) } returns Unit
  4. // Create the navigation view to test
  5. val navigationView = NavigationView(navigator)
  6. // Test the button in navigation view
  7. navigationView.goToParkButton.performClick()
  8. verify { navigator.navigateTo("Park") }

This test ensures that the button tells the navigator to go where we expect. If the NavigationView view gets changed in the future, the test will throw if this expectation is broken.

  1. goToParkButton.setOnClickListener {
  2. - navigator.navigate("Park")
  3. + navigator.navigate("Parka")
  4. }
  1. navigationView.goToParkButton.performClick()
  2. // Throws as navigateTo("Park") was never called.
  3. // MockK will mention in the error that navigateTo("Parka") was called.
  4. verify { navigator.navigateTo("Park") }

Verifying that any mock functions is never called

  1. verify { navigator wasNot Called }

Verifying that a function is never called

  1. verify(inverse = true) { navigator.navigateTo("Park") }
  2. verify(exactly = 0) { navigator.navigateTo("Park") }

Verifying a function is called a certain number of times

  1. verify(exactly = 1) { navigator.navigateTo("Park") }
  2. verify(atLeast = 1, atMost = 1) { navigator.navigateTo("Park") }

Using a range

  1. verify(atLeast = 2, atMost = 3) { navigator.navigateTo("Park") }

In the sample test will be green in the following cases:

  1. Function called two times
  2. Function called three times

Verifying multiple functions

TODO: ordering, verifyAll, verifySequence, verifyOrder

Confirming all calls were verified

TODO: confirmVerified, excludeRecords