-
Notifications
You must be signed in to change notification settings - Fork 207
Mocking & Stubbing
This page provides examples on how to mock classes, objects, and functions with Mockito-Kotlin.
To find more information on Mockito-Core, see the official Mockito documentation.
Mockito-Kotlin provides a set of Kotlin top-level functions to use instead of Mockito's static methods, such as mock(), any() and eq(). When importing these functions, be careful to import them from the org.mockito.kotlin package.
When calling mock(), the type can usually be inferred automatically:
val myMock: MyClass = mock()
val myMock = mock<MyClass>() // AlternativePassing a new mock as a parameter becomes:
myClass.test(mock())Mockito-Kotlin provides whenever in favor of when (which is a keyword in the Kotlin language). Basic usage stays the same:
whenever(mock.stringValue()).thenReturn("test")Alternatively, you can use DSL stubbing syntax to pass a lambda expression to mock(). The lambda expression is of type KStubbing<T>.() -> Unit, where T is the type of the mocked class. KStubbing<T> provides a method on which takes a function T.() -> R, so you can directly call the method to mock:
val myMock = mock<MyClass> {
on { stringValue() } doReturn "test"
}If you want to use KStubbing<T> on an already-mocked instance, use the stub extension function:
myMock.stub {
on { stringValue() } doReturn "test"
}These are special types of "scoped mocks" which are thread-local and must be closed to avoid leaking mocking state across test cases.
Use mockObject to mock object and companion object singleton types. This returns a MockedObject handle which extends AutoCloseable and must be closed to avoid leaking mocking state across tests. You can leverage Kotlin's .use {} (equivalent to Java's try-with-resources), or hold a reference and call .close() explicitly.
Example:
object MyObject { /* ... */ }
class MyClass {
companion object { /* ... */ }
}Test:
mockObject(MyObject).use { /* ... */ }mockObject(MyClass.Companion).use { /* ... */ }A common pattern is to use the mock across test-cases in a JUnit style test class:
lateinit var myObjectMock: MockedObject<MyObject>
@Before fun setUp() {
myObjectMock = mockObject(MyObject)
}
@After fun tearDown() {
myObjectMock.close()
}After mocking, you can stub and verify the object just like a normal mock:
whenever(MyObject.foo(any())).thenReturn( /* ... */ )
verify(MyObject).foo(any())You can also apply stubbing by passing a KStubbing lambda:
mockObject(MyObject) {
on { foo(any()) } doReturn /* ... */
}.use {
/* ... */
}Use mockConstruction. It returns a MockedConstruction handle which must be closed like other scoped mocks.
mockConstruction<MyClass>().use {
val m = MyClass() // `m` is a mock
}You can also apply stubbing at the time of construction with a MockedConstruction.MockInitializer lambda:
mockConstruction<MyClass> { mock, context ->
println(context.arguments)
whenever(mock.foo()).thenReturn(42)
}.use {
/* ... */
}Generally, Kotlin developers do not need to think about static methods - there is no "static" keyword in the language. But you may need to mock static methods from Java code.
Use mockStatic to mock static methods on the given class. It returns a MockedStatic handle which must be closed like other scoped mocks.
Example Java code:
public class MyJavaClass {
public static String foo() { /* ... */ }
}Test:
mockStatic<MyJavaClass>().use {
whenever(MyJavaClass.foo()).thenReturn( /* ... */ )
}Warning
Do not use mockStatic to mock @JvmStatic-marked methods on object or companion objects. This does not work in all scenarios. Use mockObject.
Use mockExtensionFun to mock top-level extension functions. It returns a MockedStatic handle which must be closed like other scoped mocks.
Example:
fun String.isHello(): Boolean = this == "Hello"mockExtensionFun(String::isHello).use {
whenever("test".isHello()).thenReturn(true)
println("test".isHello()) // "true"
}When using matchers, all arguments including the receiver must use matchers:
fun String.hasPrefix(prefix: String): Boolean = this.startsWith(prefix)
mockExtensionFun(String::hasPrefix).use {
whenever(any<String>().hasPrefix(eq("foo"))).thenReturn(true)
println("bar".hasPrefix("foo")) // "true"
}