when and do*

Mockito provides two similar approaches for stubbing behaviour on a mock: the when method and the do* family of methods.

Most stubs in Mockito are written with when at the beginning of the line, following the format “when the method is called then return something”. Stubs written with the when method look like this:

  1. val mockedFile = mock(File::class.java)
  2. `when`(mockedFile.read()).thenReturn("hello world")

Sometimes this syntax cannot be used in Mockito, so an alternative approach is available. doReturn and the related doThrow, doAnswer, doNothing, and doCallRealMethod methods are used for void methods, spies, and other occasions where the when method cannot be used. Stubs written with the do* family of methods look like this:

  1. val mockedFile = mock(File::class.java)
  2. doReturn("hello world").`when`(mockedFile).read()

In MockK, all stubs can be written with the every method. every starts a stubbing block and uses anonymous functions and infix functions to define the stub. The syntax looks like this:

  1. val mockedFile = mockk<File>()
  2. every { mockedFile.read() } returns "hello world"

MockK provides alternatives for many types of answers that Mockito supports for stubbing.

thenReturn/doReturn

Returning a value is probably the most common stub to create. In Mockito, the syntax can look like one of two approaches:

  1. val mockedFile = mock(File::class.java)
  2. `when`(mockedFile.read()).thenReturn("hello world")
  3. doReturn("hello world").`when`(mockedFile).read()

In MockK, an infix function is used instead.

  1. val mockedFile = mockk<File>()
  2. every { mockedFile.read() } returns "hello world"

thenThrow/doThrow

Rather than returning values, stubs can throw errors. Mockito lets exceptions be specified with one of two approaches:

  1. val mockedFile = mock(File::class.java)
  2. `when`(mockedFile.read()).thenThrow(RuntimeException())
  3. doThrow(RuntimeException()).`when`(mockedFile).read()

MockK provides the throws infix method to throw in stubs.

  1. val mockedFile = mockk<File>()
  2. every { mockedFile.read() } throws RuntimeException()

doNothing

See Migrating from Mockito: void methods

thenAnswer/then/doAnswer

Mockito allows arbitrary callbacks to be used for stubs with the Answer interface. Answer only contains a single method, so Kotlin allows a function literal to be used instead through SAM conversion.

  1. val mockedFile = mock(File::class.java)
  2. `when`(mockedFile.write(any())).thenAnswer { invocation ->
  3. println("called with arguments: " + invocation.arguments.joinToString())
  4. Unit
  5. }
  6. `when`(mockedFile.write(any())).then { invocation ->
  7. println("called with arguments: " + invocation.arguments.joinToString())
  8. Unit
  9. }
  10. doAnswer { invocation ->
  11. println("called with arguments: " + invocation.arguments.joinToString())
  12. Unit
  13. }.`when`(mockedFile).write(any())

MockK provides an equivalent infix function that also uses function literals.

  1. val mockedFile = mockk<File>()
  2. every { mockedFile.write(any()) } answers { call ->
  3. println("called with arguments: " + call.invocation.args.joinToString())
  4. Unit
  5. }

Consecutive calls

Mockito additionally lets different return values be stubbed for the same method call, such as for mocking an iterator.

  1. val mockedFile = mock(File::class.java)
  2. // Chain multiple calls
  3. `when`(mockedFile.read()).thenReturn("read 1").thenReturn("read 2").thenReturn("read 3")
  4. // Shorthand
  5. `when`(mockedFile.read()).thenReturn("read 1", "read 2", "read 3")
  6. doReturn("read 1", "read 2", "read 3").`when`(mockedFile).read()
  7. // Use different answer types
  8. `when`(mockedFile.read())
  9. .thenReturn("successful read")
  10. .thenThrow(RuntimeException())

Additional answers is supported in MockK using various infix functions.

  1. val mockedFile = mockk<File>()
  2. // Chain multiple calls
  3. every { mockedFile.read() } returns "read 1" andThen "read 2" andThen "read 3"
  4. // Shorthand using a list
  5. every { mockedFile.read() } returnsMany listOf("read 1", "read 2", "read 3")
  6. every { mockedFile.read() } andThenMany listOf("read 1", "read 2", "read 3")
  7. // Use different answer types
  8. every { mockedFile.read() } returns "successful read" andThenThrows RuntimeException()

Coroutines

As MockK uses function literals to create stubs, small changes are needed to stub suspend functions. MockK provides functions prefixed with co as equivalents to other functions, such as coEvery and coAnswers. See Coroutines and suspend functions for more details.

  1. val mockedFile = mockk<File>()
  2. coEvery { mockedFile.readAsync() } returns "hello world"
  3. coEvery { mockedFile.writeAsync(any()) } coAnswers { call ->
  4. doAsyncWork()
  5. Unit
  6. }