when
and do*
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:
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:
val mockedFile = mock(File::class.java)
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 to define the stub. The syntax looks like this:
val mockedFile = mockk<File>()
every { mockedFile.read() } returns "hello world"
MockK provides alternatives for many types of answers that Mockito supports for stubbing.
val mockedFile = mock(File::class.java)
`when`(mockedFile.read()).thenReturn("hello world")
doReturn("hello world").`when`(mockedFile).read()
In MockK, an infix function is used instead.
thenThrow
/doThrow
Rather than returning values, stubs can throw errors. Mockito lets exceptions be specified with one of two approaches:
val mockedFile = mock(File::class.java)
`when`(mockedFile.read()).thenThrow(RuntimeException())
doThrow(RuntimeException()).`when`(mockedFile).read()
MockK provides the throws
infix method to throw in stubs.
every { mockedFile.read() } throws RuntimeException()
See
thenAnswer
/then
/doAnswer
val mockedFile = mock(File::class.java)
`when`(mockedFile.write(any())).thenAnswer { invocation ->
println("called with arguments: " + invocation.arguments.joinToString())
Unit
}
`when`(mockedFile.write(any())).then { invocation ->
println("called with arguments: " + invocation.arguments.joinToString())
Unit
}
doAnswer { invocation ->
Unit
}.`when`(mockedFile).write(any())
MockK provides an equivalent infix function that also uses function literals.
Mockito additionally lets different return values be stubbed for the same method call, such as for mocking an iterator.
val mockedFile = mock(File::class.java)
// Chain multiple calls
`when`(mockedFile.read()).thenReturn("read 1").thenReturn("read 2").thenReturn("read 3")
`when`(mockedFile.read()).thenReturn("read 1", "read 2", "read 3")
doReturn("read 1", "read 2", "read 3").`when`(mockedFile).read()
// Use different answer types
`when`(mockedFile.read())
.thenReturn("successful read")
.thenThrow(RuntimeException())
Additional answers is supported in MockK using various infix functions.
val mockedFile = mockk<File>()
// Chain multiple calls
every { mockedFile.read() } returns "read 1" andThen "read 2" andThen "read 3"
// Shorthand using a list
every { mockedFile.read() } returnsMany listOf("read 1", "read 2", "read 3")
every { mockedFile.read() } andThenMany listOf("read 1", "read 2", "read 3")
// Use different answer types
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.
val mockedFile = mockk<File>()
coEvery { mockedFile.readAsync() } returns "hello world"
coEvery { mockedFile.writeAsync(any()) } coAnswers { call ->
doAsyncWork()