Skip to content

Commit 4acf020

Browse files
jselboJoshua Selbo
andauthored
Update MockSettings usage (#560)
Add `strictness` configuration and mark `lenient` as deprecated. Also allow for configuring a `defaultAnswer` for static mocks. Co-authored-by: Joshua Selbo <jselbo@meta.com>
1 parent c74d4d7 commit 4acf020

File tree

2 files changed

+78
-18
lines changed

2 files changed

+78
-18
lines changed

mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package org.mockito.kotlin
2727

28-
import org.mockito.Incubating
2928
import org.mockito.MockSettings
3029
import org.mockito.MockedConstruction
3130
import org.mockito.MockedStatic
@@ -51,7 +50,8 @@ import kotlin.reflect.KClass
5150
* @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
5251
* @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
5352
* @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
54-
* @param lenient Lenient mocks bypass "strict stubbing" validation.
53+
* @param lenient (DEPRECATED) Lenient mocks bypass "strict stubbing" validation.
54+
* @param strictness Specifies strictness level for the mock.
5555
*/
5656
inline fun <reified T : Any> mock(
5757
extraInterfaces: Array<out KClass<out Any>>? = null,
@@ -63,9 +63,10 @@ inline fun <reified T : Any> mock(
6363
verboseLogging: Boolean = false,
6464
invocationListeners: Array<InvocationListener>? = null,
6565
stubOnly: Boolean = false,
66-
@Incubating useConstructor: UseConstructor? = null,
67-
@Incubating outerInstance: Any? = null,
68-
@Incubating lenient: Boolean = false
66+
useConstructor: UseConstructor? = null,
67+
outerInstance: Any? = null,
68+
lenient: Boolean = false,
69+
strictness: Strictness? = if (lenient) Strictness.LENIENT else null,
6970
): T {
7071
return Mockito.mock(
7172
T::class.java,
@@ -81,7 +82,7 @@ inline fun <reified T : Any> mock(
8182
stubOnly = stubOnly,
8283
useConstructor = useConstructor,
8384
outerInstance = outerInstance,
84-
lenient = lenient
85+
strictness = strictness
8586
)
8687
)!!
8788
}
@@ -100,7 +101,8 @@ inline fun <reified T : Any> mock(
100101
* @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
101102
* @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
102103
* @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
103-
* @param lenient Lenient mocks bypass "strict stubbing" validation.
104+
* @param lenient (DEPRECATED) Lenient mocks bypass "strict stubbing" validation.
105+
* @param strictness Specifies strictness level for the mock.
104106
*/
105107
inline fun <reified T : Any> mock(
106108
extraInterfaces: Array<out KClass<out Any>>? = null,
@@ -112,9 +114,10 @@ inline fun <reified T : Any> mock(
112114
verboseLogging: Boolean = false,
113115
invocationListeners: Array<InvocationListener>? = null,
114116
stubOnly: Boolean = false,
115-
@Incubating useConstructor: UseConstructor? = null,
116-
@Incubating outerInstance: Any? = null,
117-
@Incubating lenient: Boolean = false,
117+
useConstructor: UseConstructor? = null,
118+
outerInstance: Any? = null,
119+
lenient: Boolean = false,
120+
strictness: Strictness? = if (lenient) Strictness.LENIENT else null,
118121
stubbing: KStubbing<T>.(T) -> Unit
119122
): T {
120123
return Mockito.mock(
@@ -131,7 +134,7 @@ inline fun <reified T : Any> mock(
131134
stubOnly = stubOnly,
132135
useConstructor = useConstructor,
133136
outerInstance = outerInstance,
134-
lenient = lenient
137+
strictness = strictness,
135138
)
136139
).apply { KStubbing(this).stubbing(this) }!!
137140
}
@@ -151,7 +154,8 @@ inline fun <reified T : Any> mock(
151154
* @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
152155
* @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
153156
* @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
154-
* @param lenient Lenient mocks bypass "strict stubbing" validation.
157+
* @param lenient (DEPRECATED) Lenient mocks bypass "strict stubbing" validation.
158+
* @param strictness Specifies strictness level for the mock.
155159
*/
156160
fun withSettings(
157161
extraInterfaces: Array<out KClass<out Any>>? = null,
@@ -163,9 +167,10 @@ fun withSettings(
163167
verboseLogging: Boolean = false,
164168
invocationListeners: Array<InvocationListener>? = null,
165169
stubOnly: Boolean = false,
166-
@Incubating useConstructor: UseConstructor? = null,
167-
@Incubating outerInstance: Any? = null,
168-
@Incubating lenient: Boolean = false
170+
useConstructor: UseConstructor? = null,
171+
outerInstance: Any? = null,
172+
lenient: Boolean = false,
173+
strictness: Strictness? = if (lenient) Strictness.LENIENT else null,
169174
): MockSettings = Mockito.withSettings().apply {
170175
extraInterfaces?.let { extraInterfaces(*it.map { it.java }.toTypedArray()) }
171176
name?.let { name(it) }
@@ -178,16 +183,19 @@ fun withSettings(
178183
if (stubOnly) stubOnly()
179184
useConstructor?.let { useConstructor(*it.args) }
180185
outerInstance?.let { outerInstance(it) }
181-
if (lenient) strictness(Strictness.LENIENT)
186+
strictness?.let { strictness(it) }
182187
}
183188

184189
/**
185190
* Creates a thread-local mock for static methods on [T].
186191
*
192+
* @param defaultAnswer the default answer when invoking static methods.
187193
* @see Mockito.mockStatic
188194
*/
189-
inline fun <reified T> mockStatic(): MockedStatic<T> {
190-
return Mockito.mockStatic(T::class.java)
195+
inline fun <reified T> mockStatic(
196+
defaultAnswer: Answer<Any>? = null,
197+
): MockedStatic<T> {
198+
return Mockito.mockStatic(T::class.java, withSettings(defaultAnswer = defaultAnswer))
191199
}
192200

193201
/**

tests/src/test/kotlin/test/MockingTest.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import org.mockito.kotlin.whenever
1313
import org.mockito.kotlin.any
1414
import org.junit.Test
1515
import org.mockito.Mockito
16+
import org.mockito.MockitoSession
1617
import org.mockito.exceptions.verification.WantedButNotInvoked
1718
import org.mockito.invocation.DescribedInvocation
1819
import org.mockito.kotlin.argumentCaptor
1920
import org.mockito.kotlin.mockConstruction
2021
import org.mockito.kotlin.mockStatic
2122
import org.mockito.listeners.InvocationListener
2223
import org.mockito.mock.SerializableMode.BASIC
24+
import org.mockito.quality.Strictness
2325
import java.io.PrintStream
2426
import java.io.Serializable
2527
import java.util.*
@@ -242,6 +244,49 @@ class MockingTest : TestBase() {
242244
expect(result).toNotBeNull()
243245
}
244246

247+
@Test
248+
fun mock_strictness_default() {
249+
/* Given */
250+
val session = Mockito.mockitoSession().strictness(Strictness.STRICT_STUBS).startMocking()
251+
252+
/* When */
253+
val result = mock<SynchronousFunctions>()
254+
whenever(result.intResult()).thenReturn(42)
255+
256+
/* Then */
257+
expectErrorWithMessage("Unnecessary stubbings detected") on {
258+
session.finishMocking()
259+
}
260+
}
261+
262+
@Test
263+
fun mock_withSettingsAPI_lenient() {
264+
/* Given */
265+
val session = Mockito.mockitoSession().strictness(Strictness.STRICT_STUBS).startMocking()
266+
267+
/* When */
268+
val result = mock<SynchronousFunctions>(lenient = true)
269+
whenever(result.intResult()).thenReturn(42)
270+
271+
/* Then */
272+
// Verify no "Unnecessary stubbings detected" exception
273+
session.finishMocking()
274+
}
275+
276+
@Test
277+
fun mock_withSettingsAPI_strictness_lenient() {
278+
/* Given */
279+
val session = Mockito.mockitoSession().strictness(Strictness.STRICT_STUBS).startMocking()
280+
281+
/* When */
282+
val result = mock<SynchronousFunctions>(strictness = Strictness.LENIENT)
283+
whenever(result.intResult()).thenReturn(42)
284+
285+
/* Then */
286+
// Verify no "Unnecessary stubbings detected" exception
287+
session.finishMocking()
288+
}
289+
245290
@Test
246291
fun mockStubbing_withSettingsAPI_extraInterfaces() {
247292
/* Given */
@@ -399,6 +444,13 @@ class MockingTest : TestBase() {
399444
}
400445
}
401446

447+
@Test
448+
fun mockStatic_defaultAnswer_stubbing() {
449+
mockStatic<SomeObject>(defaultAnswer = Mockito.CALLS_REAL_METHODS).use {
450+
expect(SomeObject.aStaticMethodReturningString()).toBe("Some Value")
451+
}
452+
}
453+
402454
@Test
403455
fun mockConstruction_basic() {
404456
mockConstruction<Open>().use { mockedConstruction ->

0 commit comments

Comments
 (0)