io.mockk.API.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mockk-dsl-js Show documentation
Show all versions of mockk-dsl-js Show documentation
JS MockK DSL providing API for MockK implementation
@file:Suppress("DEPRECATION")
package io.mockk
import io.mockk.InternalPlatformDsl.toStr
import io.mockk.MockKGateway.CallRecorder
import io.mockk.MockKGateway.VerificationParameters
import kotlin.coroutines.experimental.Continuation
import kotlin.reflect.KClass
/**
* Exception thrown by library
*/
class MockKException(message: String, ex: Throwable? = null) : RuntimeException(message, ex)
/**
* DSL entry points.
*/
@Suppress("NOTHING_TO_INLINE")
object MockKDsl {
/**
* Builds a new mock for specified class
*/
inline fun internalMockk(
name: String? = null,
relaxed: Boolean = false,
vararg moreInterfaces: KClass<*>,
relaxUnitFun: Boolean = false,
block: T.() -> Unit = {}
): T {
val mock = MockKGateway.implementation().mockFactory.mockk(
T::class,
name,
relaxed,
moreInterfaces,
relaxUnitFun
)
block(mock)
return mock
}
/**
* Builds a new spy for specified class. Initializes object via default constructor.
*/
inline fun internalSpyk(
objToCopy: T,
name: String? = null,
vararg moreInterfaces: KClass<*>,
recordPrivateCalls: Boolean = false,
block: T.() -> Unit = {}
): T {
val spy = MockKGateway.implementation().mockFactory.spyk(
null,
objToCopy,
name,
moreInterfaces,
recordPrivateCalls
)
block(spy)
return spy
}
/**
* Builds a new spy for specified class. Copies fields from provided object
*/
inline fun internalSpyk(
name: String? = null,
vararg moreInterfaces: KClass<*>,
recordPrivateCalls: Boolean = false,
block: T.() -> Unit = {}
): T {
val spy = MockKGateway.implementation().mockFactory.spyk(
T::class,
null,
name,
moreInterfaces,
recordPrivateCalls
)
block(spy)
return spy
}
/**
* Creates new capturing slot
*/
inline fun internalSlot() = CapturingSlot()
/**
* Starts a block of stubbing. Part of DSL.
*/
fun internalEvery(stubBlock: MockKMatcherScope.() -> T): MockKStubScope =
MockKGateway.implementation().stubber.every(stubBlock, null)
/**
* Starts a block of stubbing for coroutines. Part of DSL.
*/
fun internalCoEvery(stubBlock: suspend MockKMatcherScope.() -> T): MockKStubScope =
MockKGateway.implementation().stubber.every(null, stubBlock)
/**
* Verifies calls happened in the past. Part of DSL
*/
fun internalVerify(
ordering: Ordering = Ordering.UNORDERED,
inverse: Boolean = false,
atLeast: Int = 1,
atMost: Int = Int.MAX_VALUE,
exactly: Int = -1,
timeout: Long = 0,
verifyBlock: MockKVerificationScope.() -> Unit
) {
internalCheckExactlyAtMostAtLeast(exactly, atLeast, atMost, ordering)
val min = if (exactly != -1) exactly else atLeast
val max = if (exactly != -1) exactly else atMost
MockKGateway.implementation().verifier.verify(
VerificationParameters(ordering, min, max, inverse, timeout),
verifyBlock,
null
)
}
/**
* Verify for coroutines
*/
fun internalCoVerify(
ordering: Ordering = Ordering.UNORDERED,
inverse: Boolean = false,
atLeast: Int = 1,
atMost: Int = Int.MAX_VALUE,
exactly: Int = -1,
timeout: Long = 0,
verifyBlock: suspend MockKVerificationScope.() -> Unit
) {
internalCheckExactlyAtMostAtLeast(exactly, atLeast, atMost, ordering)
val min = if (exactly != -1) exactly else atLeast
val max = if (exactly != -1) exactly else atMost
MockKGateway.implementation().verifier.verify(
VerificationParameters(ordering, min, max, inverse, timeout),
null,
verifyBlock
)
}
@PublishedApi
internal fun internalCheckExactlyAtMostAtLeast(exactly: Int, atLeast: Int, atMost: Int, ordering: Ordering) {
if (exactly != -1 && (atLeast != 1 || atMost != Int.MAX_VALUE)) {
throw MockKException("specify either atLeast/atMost or exactly")
}
if (exactly < -1) {
throw MockKException("exactly should be positive")
}
if (atLeast < 0) {
throw MockKException("atLeast should be positive")
}
if (atMost < 0) {
throw MockKException("atMost should be positive")
}
if (atLeast > atMost) {
throw MockKException("atLeast should less or equal atMost")
}
if (ordering != Ordering.UNORDERED) {
if (atLeast != 1 || atMost != Int.MAX_VALUE || exactly != -1) {
throw MockKException("atLeast, atMost, exactly is only allowed in unordered verify block")
}
}
}
/**
* Shortcut for ordered calls verification
*/
fun internalVerifyOrder(
inverse: Boolean = false,
verifyBlock: MockKVerificationScope.() -> Unit
) {
internalVerify(Ordering.ORDERED, inverse, verifyBlock = verifyBlock)
}
/**
* Shortcut for all calls verification
*/
fun internalVerifyAll(
inverse: Boolean = false,
verifyBlock: MockKVerificationScope.() -> Unit
) {
internalVerify(Ordering.ALL, inverse, verifyBlock = verifyBlock)
}
/**
* Shortcut for sequence calls verification
*/
fun internalVerifySequence(
inverse: Boolean = false,
verifyBlock: MockKVerificationScope.() -> Unit
) {
internalVerify(Ordering.SEQUENCE, inverse, verifyBlock = verifyBlock)
}
/**
* Resets information associated with mock
*/
inline fun internalClearMocks(
vararg mocks: Any,
answers: Boolean = true,
recordedCalls: Boolean = true,
childMocks: Boolean = true
) {
MockKGateway.implementation().clearer.clear(
mocks,
MockKGateway.ClearOptions(answers, recordedCalls, childMocks)
)
}
/**
* Registers instance factory and returns object able to do deregistration.
*/
inline fun internalRegisterInstanceFactory(noinline instanceFactory: () -> T): Deregisterable {
val factoryObj = object : MockKGateway.InstanceFactory {
override fun instantiate(cls: KClass<*>): Any? {
if (T::class == cls) {
return instanceFactory()
}
return null
}
}
MockKGateway.implementation().instanceFactoryRegistry.registerFactory(factoryObj)
return object : Deregisterable {
override fun deregister() {
MockKGateway.implementation().instanceFactoryRegistry.deregisterFactory(factoryObj)
}
}
}
/**
* Executes block of code with registering and unregistering instance factory.
*/
inline fun internalWithInstanceFactory(noinline instanceFactory: () -> T, block: () -> R): R {
return internalRegisterInstanceFactory(instanceFactory).use {
block()
}
}
/**
* Declares static mockk. Deprecated
*/
inline fun internalStaticMockk() = MockKStaticScope(T::class)
/**
* Declares static mockk. Deprecated
*/
inline fun internalStaticMockk(vararg kClass: KClass) = MockKStaticScope(*kClass)
/**
* Declares object mockk. Deprecated
*/
inline fun internalObjectMockk(objs: Array, recordPrivateCalls: Boolean = false) =
MockKObjectScope(*objs, recordPrivateCalls = recordPrivateCalls)
/**
* Declares constructor mockk. Deprecated
*/
inline fun internalConstructorMockk(
recordPrivateCalls: Boolean = false,
localToThread: Boolean = false
) =
MockKConstructorScope(T::class, recordPrivateCalls, localToThread)
/**
* Builds a mock for a class. Deprecated
*/
inline fun internalMockkClass(
type: KClass,
name: String?,
relaxed: Boolean,
vararg moreInterfaces: KClass<*>,
relaxUnitFun: Boolean = false,
block: T.() -> Unit
): T {
val mock = MockKGateway.implementation().mockFactory.mockk(type, name, relaxed, moreInterfaces, relaxUnitFun)
block(mock)
return mock
}
/**
* Initializes
*/
inline fun internalInitAnnotatedMocks(
targets: List,
overrideRecordPrivateCalls: Boolean = false,
relaxUnitFun: Boolean = false,
relaxed: Boolean = false
) =
MockKGateway.implementation().mockInitializer.initAnnotatedMocks(
targets,
overrideRecordPrivateCalls,
relaxUnitFun,
relaxed
)
/**
* Object mockk
*/
inline fun internalMockkObject(vararg objects: Any, recordPrivateCalls: Boolean = false) {
val factory = MockKGateway.implementation().objectMockFactory
objects.forEach {
val cancellation = factory.objectMockk(it, recordPrivateCalls)
internalClearMocks(it)
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.OBJECT)
.cancelPut(it, cancellation)
}
}
/**
* Cancel object mocks.
*/
inline fun internalUnmockkObject(vararg objects: Any) {
objects.forEach {
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.OBJECT)
.cancel(it)
}
}
/**
* Clear object mocks.
*/
inline fun internalClearObjectMockk(
vararg objects: Any,
answers: Boolean = true,
recordedCalls: Boolean = true,
childMocks: Boolean = true
) {
for (obj in objects) {
MockKGateway.implementation().objectMockFactory.clear(obj, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
/**
* Static mockk
*/
inline fun internalMockkStatic(vararg classes: KClass<*>) {
val factory = MockKGateway.implementation().staticMockFactory
classes.forEach {
val cancellation = factory.staticMockk(it)
internalClearStaticMockk(it)
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.STATIC)
.cancelPut(it, cancellation)
}
}
/**
* Cancel static mocks.
*/
inline fun internalUnmockkStatic(vararg classes: KClass<*>) {
classes.forEach {
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.STATIC)
.cancel(it)
}
}
/**
* Clear static mocks.
*/
inline fun internalClearStaticMockk(
vararg classes: KClass<*>,
answers: Boolean = true,
recordedCalls: Boolean = true,
childMocks: Boolean = true
) {
for (type in classes) {
MockKGateway.implementation().staticMockFactory.clear(type, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
/**
* Constructor mockk
*/
inline fun internalMockkConstructor(
vararg classes: KClass<*>,
recordPrivateCalls: Boolean = false,
localToThread: Boolean = true
) {
val factory = MockKGateway.implementation().constructorMockFactory
classes.forEach {
val cancellation = factory.constructorMockk(it, recordPrivateCalls, localToThread)
internalClearConstructorMockk(it)
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.CONSTRUCTOR)
.cancelPut(it, cancellation)
}
}
/**
* Cancel constructor mocks.
*/
inline fun internalUnmockkConstructor(vararg classes: KClass<*>) {
classes.forEach {
MockKCancellationRegistry
.subRegistry(MockKCancellationRegistry.Type.CONSTRUCTOR)
.cancel(it)
}
}
/**
* Clear constructor mocks.
*/
inline fun internalClearConstructorMockk(
vararg classes: KClass<*>,
answers: Boolean = true,
recordedCalls: Boolean = true,
childMocks: Boolean = true
) {
for (type in classes) {
MockKGateway.implementation().constructorMockFactory.clear(type, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
/**
* Unmockk everything
*/
inline fun internalUnmockkAll() {
MockKCancellationRegistry.cancelAll()
}
inline fun internalClearAllMocks(
answers: Boolean = true,
recordedCalls: Boolean = true,
childMocks: Boolean = true,
regularMocks: Boolean = true,
objectMocks: Boolean = true,
staticMocks: Boolean = true,
constructorMocks: Boolean = true
) {
val options = MockKGateway.ClearOptions(answers, recordedCalls, childMocks)
val implementation = MockKGateway.implementation()
if (regularMocks) {
implementation.clearer.clearAll(options)
}
if (objectMocks) {
implementation.objectMockFactory.clearAll(options)
}
if (staticMocks) {
implementation.staticMockFactory.clearAll(options)
}
if (constructorMocks) {
implementation.constructorMockFactory.clearAll(options)
}
}
}
/**
* Verification ordering
*/
enum class Ordering {
/**
* Order is not important. Some calls just should happen
*/
UNORDERED,
/**
* Order is not important. All calls should happen
*/
ALL,
/**
* Order is important, but not all calls are checked
*/
ORDERED,
/**
* Order is important and all calls should be specified
*/
SEQUENCE
}
/**
* Basic stub/verification scope. Part of DSL.
*
* Inside of the scope you can interact with mocks.
* You can chain calls to the mock, put argument matchers instead of arguments,
* capture arguments, combine matchers in and/or/not expressions.
*
* It's not required to specify all arguments as matchers,
* if the argument value is constant it's automatically replaced with eq() matcher.
* .
* Handling arguments that have defaults fetched from function (alike System.currentTimeMillis())
* can be an issue, because it's not a constant. Such arguments can always be replaced
* with some matcher.
*
* Provided information is gathered and associated with mock
*/
open class MockKMatcherScope(
@PublishedApi
internal val callRecorder: CallRecorder,
val lambda: CapturingSlot>
) {
inline fun match(matcher: Matcher): T {
return callRecorder.matcher(matcher, T::class)
}
inline fun match(noinline matcher: (T) -> Boolean): T = matchNullable {
if (it == null) {
false
} else {
matcher(it)
}
}
inline fun matchNullable(noinline matcher: (T?) -> Boolean): T =
match(FunctionMatcher(matcher, T::class))
inline fun eq(value: T, inverse: Boolean = false): T = match(EqMatcher(value, inverse = inverse))
inline fun neq(value: T): T = eq(value, true)
inline fun refEq(value: T, inverse: Boolean = false): T =
match(EqMatcher(value, ref = true, inverse = inverse))
inline fun nrefEq(value: T) = refEq(value, true)
inline fun any(): T = match(ConstantMatcher(true))
inline fun capture(lst: MutableList): T = match(CaptureMatcher(lst, T::class))
inline fun capture(lst: CapturingSlot): T = match(CapturingSlotMatcher(lst, T::class))
inline fun captureNullable(lst: MutableList): T = match(CaptureNullableMatcher(lst, T::class))
inline fun > cmpEq(value: T): T = match(ComparingMatcher(value, 0, T::class))
inline fun > more(value: T, andEquals: Boolean = false): T =
match(ComparingMatcher(value, if (andEquals) 2 else 1, T::class))
inline fun > less(value: T, andEquals: Boolean = false): T =
match(ComparingMatcher(value, if (andEquals) -2 else -1, T::class))
inline fun > range(
from: T,
to: T,
fromInclusive: Boolean = true,
toInclusive: Boolean = true
): T = and(more(from, fromInclusive), less(to, toInclusive))
inline fun and(left: T, right: T) = match(AndOrMatcher(true, left, right))
inline fun or(left: T, right: T) = match(AndOrMatcher(false, left, right))
inline fun not(value: T) = match(NotMatcher(value))
inline fun isNull(inverse: Boolean = false) = match(NullCheckMatcher(inverse))
inline fun ofType(cls: KClass) = match(OfTypeMatcher(cls))
inline fun ofType() = match(OfTypeMatcher(T::class))
inline fun R, R> invoke() = match(InvokeMatcher { it() })
inline fun R, R, A1> invoke(arg1: A1) = match(InvokeMatcher { it(arg1) })
inline fun R, R, A1, A2> invoke(arg1: A1, arg2: A2) =
match(InvokeMatcher { it(arg1, arg2) })
inline fun R, R, A1, A2, A3> invoke(arg1: A1, arg2: A2, arg3: A3) =
match(InvokeMatcher { it(arg1, arg2, arg3) })
inline fun R, R, A1, A2, A3, A4> invoke(arg1: A1, arg2: A2, arg3: A3, arg4: A4) =
match(InvokeMatcher { it(arg1, arg2, arg3, arg4) })
inline fun R, R, A1, A2, A3, A4, A5> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5) })
inline fun R, R, A1, A2, A3, A4, A5, A6> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13
) = match(InvokeMatcher { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20,
arg21: A21
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20,
arg21
)
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22> invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20,
arg21: A21,
arg22: A22
) = match(InvokeMatcher {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20,
arg21,
arg22
)
})
inline fun R, R> coInvoke() =
match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it() } })
inline fun R, R, A1> coInvoke(arg1: A1) =
match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1) } })
inline fun R, R, A1, A2> coInvoke(arg1: A1, arg2: A2) =
match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2) } })
inline fun R, R, A1, A2, A3> coInvoke(arg1: A1, arg2: A2, arg3: A3) =
match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2, arg3) } })
inline fun R, R, A1, A2, A3, A4> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4
) = match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2, arg3, arg4) } })
inline fun R, R, A1, A2, A3, A4, A5> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5
) = match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2, arg3, arg4, arg5) } })
inline fun R, R, A1, A2, A3, A4, A5, A6> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6
) = match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2, arg3, arg4, arg5, arg6) } })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7
) = match(InvokeMatcher { InternalPlatformDsl.runCoroutine { it(arg1, arg2, arg3, arg4, arg5, arg6, arg7) } })
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20,
arg21: A21
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20,
arg21
)
}
})
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22> coInvoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16,
arg17: A17,
arg18: A18,
arg19: A19,
arg20: A20,
arg21: A21,
arg22: A22
) = match(InvokeMatcher {
InternalPlatformDsl.runCoroutine {
it(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16,
arg17,
arg18,
arg19,
arg20,
arg21,
arg22
)
}
})
inline fun allAny(): T = match(AllAnyMatcher())
inline fun array(vararg matchers: Matcher): T = match(ArrayMatcher(matchers.toList()))
@Suppress("NOTHING_TO_INLINE")
inline fun R.hint(cls: KClass, n: Int = 1): R {
callRecorder.hintNextReturnType(cls, n)
return this
}
/**
* Captures lambda function. Captured lambda<(A1, A2, ...) -> R>().invoke(...) can be used in answer scope.
*/
@Suppress("UNCHECKED_CAST")
inline fun > captureLambda(): T {
val matcher = CapturingSlotMatcher(lambda as CapturingSlot, T::class)
return callRecorder.matcher(matcher, T::class)
}
/**
* Captures coroutine. Captured coroutine R>().coInvoke(...) can be used in answer scope.
*/
@Suppress("UNCHECKED_CAST")
inline fun captureCoroutine(): T {
val matcher = CapturingSlotMatcher(lambda as CapturingSlot, T::class)
return callRecorder.matcher(matcher, T::class)
}
inline fun coMatch(noinline matcher: suspend (T) -> Boolean): T = match {
InternalPlatformDsl.runCoroutine {
matcher(it)
}
}
inline fun coMatchNullable(noinline matcher: suspend (T?) -> Boolean): T = matchNullable {
InternalPlatformDsl.runCoroutine {
matcher(it)
}
}
operator fun Any.get(name: String) =
DynamicCall(this, name, { any() })
infix fun Any.invoke(name: String) =
DynamicCallLong(this, name, { any() })
infix fun Any.invokeNoArgs(name: String) =
invoke(name).withArguments(listOf())
infix fun Any.getProperty(name: String) =
InternalPlatformDsl.dynamicGet(this, name)
infix fun Any.setProperty(name: String) = DynamicSetProperty(this, name)
class DynamicSetProperty(val self: Any, val name: String) {
infix fun value(value: Any?) {
InternalPlatformDsl.dynamicSet(self, name, value)
}
}
class DynamicCall(
val self: Any,
val methodName: String,
val anyContinuationGen: () -> Continuation<*>
) {
operator fun invoke(vararg args: Any?) =
InternalPlatformDsl.dynamicCall(self, methodName, args, anyContinuationGen)
}
class DynamicCallLong(
val self: Any,
val methodName: String,
val anyContinuationGen: () -> Continuation<*>
) {
infix fun withArguments(args: List) =
InternalPlatformDsl.dynamicCall(self, methodName, args.toTypedArray(), anyContinuationGen)
}
inline fun anyConstructed(): T =
MockKGateway.implementation().constructorMockFactory.mockPlaceholder(T::class)
}
/**
* Part of DSL. Additional operations for verification scope.
*/
class MockKVerificationScope(
callRecorder: CallRecorder,
lambda: CapturingSlot>
) : MockKMatcherScope(callRecorder, lambda) {
inline fun assert(msg: String? = null, noinline assertion: (T) -> Boolean): T =
match(AssertMatcher({ assertion(it as T) }, msg, T::class))
inline fun assertNullable(msg: String? = null, noinline assertion: (T?) -> Boolean): T =
match(AssertMatcher(assertion, msg, T::class, nullable = true))
@Deprecated("'run' seems to be too wide name, so replaced with 'withArg'", ReplaceWith("withArg(captureBlock)"))
inline fun run(noinline captureBlock: MockKAssertScope.(T) -> Unit): T = match {
MockKAssertScope(it).captureBlock(it)
true
}
@Deprecated(
"'runNullable' seems to be too wide name, so replaced with 'withNullableArg'",
ReplaceWith("withNullableArg(captureBlock)")
)
inline fun runNullable(noinline captureBlock: MockKAssertScope.(T?) -> Unit): T = matchNullable {
MockKAssertScope(it).captureBlock(it)
true
}
inline fun withArg(noinline captureBlock: MockKAssertScope.(T) -> Unit): T = run(captureBlock)
inline fun withNullableArg(noinline captureBlock: MockKAssertScope.(T?) -> Unit): T =
runNullable(captureBlock)
inline fun coAssert(msg: String? = null, noinline assertion: suspend (T) -> Boolean): T =
assert(msg) {
InternalPlatformDsl.runCoroutine {
assertion(it)
}
}
inline fun coAssertNullable(msg: String? = null, noinline assertion: suspend (T?) -> Boolean): T =
assertNullable(msg) {
InternalPlatformDsl.runCoroutine {
assertion(it)
}
}
@Deprecated(
"'coRun' seems to be too wide name, so replaced with 'coWithArg'",
ReplaceWith("withNullableArg(captureBlock)")
)
inline fun coRun(noinline captureBlock: suspend MockKAssertScope.(T) -> Unit): T = run {
InternalPlatformDsl.runCoroutine {
captureBlock(it)
}
}
@Deprecated(
"'coRunNullable' seems to be too wide name, so replaced with 'coWithNullableArg'",
ReplaceWith("withNullableArg(captureBlock)")
)
inline fun coRunNullable(noinline captureBlock: suspend MockKAssertScope.(T?) -> Unit): T =
runNullable {
InternalPlatformDsl.runCoroutine {
captureBlock(it)
}
}
inline fun coWithArg(noinline captureBlock: suspend MockKAssertScope.(T) -> Unit): T =
coRun(captureBlock)
inline fun coWithNullableArg(noinline captureBlock: suspend MockKAssertScope.(T?) -> Unit): T =
coRunNullable(captureBlock)
infix fun Any.wasNot(called: Called) {
listOf(this) wasNot called
}
@Suppress("UNUSED_PARAMETER")
infix fun List.wasNot(called: Called) {
callRecorder.wasNotCalled(this)
}
}
/**
* Part of DSL. Object to represent phrase "wasNot Called"
*/
object Called
typealias called = Called
/**
* Part of DSL. Scope for assertions on arguments during verifications.
*/
class MockKAssertScope(val actual: Any?)
fun MockKAssertScope.checkEquals(expected: Any?) {
if (!InternalPlatformDsl.deepEquals(expected, actual)) {
throw AssertionError(formatAssertMessage(actual, expected))
}
}
fun MockKAssertScope.checkEquals(msg: String, expected: Any?) {
if (!InternalPlatformDsl.deepEquals(expected, actual)) {
throw AssertionError(formatAssertMessage(actual, expected, msg))
}
}
private fun formatAssertMessage(actual: Any?, expected: Any?, message: String? = null): String {
val msgFormatted = if (message != null) "$message " else ""
return "${msgFormatted}expected [$expected] but found [$actual]"
}
/**
* Part of DSL. Object to represent phrase "just Runs"
*/
object Runs
typealias runs = Runs
/**
* Stub scope. Part of DSL
*
* Allows to specify function result
*/
class MockKStubScope(
val callRecorder: CallRecorder,
private val lambda: CapturingSlot>
) {
infix fun answers(answer: Answer): MockKAdditionalAnswerScope {
callRecorder.answer(answer)
return MockKAdditionalAnswerScope(callRecorder, lambda)
}
infix fun returns(returnValue: T) = answers(ConstantAnswer(returnValue))
infix fun returnsMany(values: List) = answers(ManyAnswersAnswer(values.allConst()))
fun returnsMany(vararg values: T) = returnsMany(values.toList())
infix fun throws(ex: Throwable) = answers(ThrowingAnswer(ex))
infix fun answers(answer: MockKAnswerScope.(Call) -> T) =
answers(FunctionAnswer { MockKAnswerScope(lambda, it).answer(it) })
infix fun propertyType(cls: KClass) = MockKStubScope(callRecorder, lambda)
infix fun nullablePropertyType(cls: KClass) = MockKStubScope(callRecorder, lambda)
infix fun coAnswers(answer: suspend MockKAnswerScope.(Call) -> T) =
answers(CoFunctionAnswer { MockKAnswerScope(lambda, it).answer(it) })
}
/**
* Part of DSL. Answer placeholder for Unit returning functions.
*/
@Suppress("UNUSED_PARAMETER")
infix fun MockKStubScope.just(runs: Runs) = answers(ConstantAnswer(Unit))
/**
* Scope to chain additional answers to reply. Part of DSL
*/
class MockKAdditionalAnswerScope(
val callRecorder: CallRecorder,
private val lambda: CapturingSlot>
) {
infix fun andThenAnswer(answer: Answer): MockKAdditionalAnswerScope {
callRecorder.answer(answer)
return this
}
infix fun andThen(returnValue: T) = andThenAnswer(ConstantAnswer(returnValue))
infix fun andThenMany(values: List) = andThenAnswer(ManyAnswersAnswer(values.allConst()))
fun andThenMany(vararg values: T) = andThenMany(values.toList())
infix fun andThenThrows(ex: Throwable) = andThenAnswer(ThrowingAnswer(ex))
infix fun andThen(answer: MockKAnswerScope.(Call) -> T) =
andThenAnswer(FunctionAnswer { MockKAnswerScope(lambda, it).answer(it) })
infix fun coAndThen(answer: suspend MockKAnswerScope.(Call) -> T) =
andThenAnswer(CoFunctionAnswer { MockKAnswerScope(lambda, it).answer(it) })
}
internal fun List.allConst() = this.map { ConstantAnswer(it) }
/**
* Scope for answering functions. Part of DSL
*/
class MockKAnswerScope(
@PublishedApi
internal val lambda: CapturingSlot>,
val call: Call
) {
val invocation = call.invocation
val matcher = call.matcher
val self
get() = invocation.self
val method
get() = invocation.method
val args
get() = invocation.args
val nArgs
get() = invocation.args.size
inline fun firstArg() = invocation.args[0] as T
inline fun secondArg() = invocation.args[1] as T
inline fun thirdArg() = invocation.args[2] as T
inline fun lastArg() = invocation.args.last() as T
inline fun arg(n: Int) = invocation.args[n] as T
@Suppress("NOTHING_TO_INLINE")
inline fun MutableList.captured() = last()
@Suppress("UNCHECKED_CAST")
inline fun > lambda() = lambda as CapturingSlot
@Suppress("UNCHECKED_CAST")
inline fun coroutine() = lambda as CapturingSlot
val nothing = null
@Suppress("UNCHECKED_CAST")
fun callOriginal(): T = call.invocation.originalCall.invoke() as T
@Suppress("UNCHECKED_CAST")
val value: B
get() = valueAny as B
val valueAny: Any?
get() = firstArg()
private val backingFieldValue: BackingFieldValue? by lazy { call.fieldValueProvider() }
@Suppress("UNCHECKED_CAST")
var fieldValue: B
set(value) {
fieldValueAny = value
}
get() = fieldValueAny as B
var fieldValueAny: Any?
set(value) {
val fv = backingFieldValue
?: throw MockKException("no backing field found for '${call.invocation.method.name}'")
fv.setter(value)
}
get() {
val fv = backingFieldValue
?: throw MockKException("no backing field found for '${call.invocation.method.name}'")
return fv.getter()
}
}
/**
* Cancelable mocking scope
*/
abstract class MockKUnmockKScope {
fun mock() {
val cancellation = doMock()
MockKCancellationRegistry.pushCancellation(cancellation)
}
fun unmock() {
val cancellation = MockKCancellationRegistry.popCancellation() ?: throw MockKException("Not mocked")
cancellation.invoke()
}
protected abstract fun doMock(): () -> Unit
abstract fun clear(answers: Boolean = true, recordedCalls: Boolean = true, childMocks: Boolean = true)
operator fun plus(scope: MockKUnmockKScope): MockKUnmockKScope = MockKUnmockKCompositeScope(this, scope)
}
typealias MockKCancellation = () -> Unit
object MockKCancellationRegistry {
enum class Type { OBJECT, STATIC, CONSTRUCTOR }
class RegistryPerType {
private val mapTl = InternalPlatformDsl.threadLocal { mutableMapOf() }
fun cancelPut(key: Any, newCancellation: MockKCancellation) {
val map = mapTl.value
map.remove(key)?.invoke()
map[key] = newCancellation
}
fun cancelAll() {
val map = mapTl.value
map.values.forEach { it() }
map.clear()
}
fun cancel(key: Any) {
mapTl.value.remove(key)?.invoke()
}
}
private val stack = InternalPlatformDsl.threadLocal { mutableListOf() }
private val perType = mapOf(
Type.OBJECT to RegistryPerType(),
Type.STATIC to RegistryPerType(),
Type.CONSTRUCTOR to RegistryPerType()
)
fun subRegistry(type: Type) = perType[type]!!
fun pushCancellation(cancellation: MockKCancellation) = stack.value.add(cancellation)
fun popCancellation(): (MockKCancellation)? {
val list = stack.value
return if (list.isEmpty())
null
else
list.removeAt(list.size - 1)
}
fun cancelAll() {
stack.value.apply { forEach { it() } }.clear()
perType.values.forEach { it.cancelAll() }
}
}
/**
* Composite of two scopes. Part of DSL
*/
class MockKUnmockKCompositeScope(
val first: MockKUnmockKScope,
val second: MockKUnmockKScope
) : MockKUnmockKScope() {
override fun doMock(): MockKCancellation {
first.mock()
second.mock()
return {
first.unmock()
second.unmock()
}
}
override fun clear(answers: Boolean, recordedCalls: Boolean, childMocks: Boolean) {
first.clear(answers, recordedCalls, childMocks)
second.clear(answers, recordedCalls, childMocks)
}
}
/**
* Scope for static mockks. Part of DSL
*/
class MockKStaticScope(vararg val staticTypes: KClass<*>) : MockKUnmockKScope() {
override fun doMock(): MockKCancellation {
val factory = MockKGateway.implementation().staticMockFactory
val cancellations = staticTypes.map {
factory.staticMockk(it)
}
return { cancellations.forEach { it() } }
}
override fun clear(answers: Boolean, recordedCalls: Boolean, childMocks: Boolean) {
for (type in staticTypes) {
MockKGateway.implementation().staticMockFactory.clear(type, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
inline fun and() = MockKStaticScope(T::class, *staticTypes)
}
/**
* Scope for object mockks. Part of DSL
*/
class MockKObjectScope(vararg val objects: Any, val recordPrivateCalls: Boolean = false) : MockKUnmockKScope() {
override fun doMock(): MockKCancellation {
val factory = MockKGateway.implementation().objectMockFactory
val cancellations = objects.map {
factory.objectMockk(it, recordPrivateCalls)
}
return { cancellations.forEach { it() } }
}
override fun clear(answers: Boolean, recordedCalls: Boolean, childMocks: Boolean) {
for (obj in objects) {
MockKGateway.implementation().objectMockFactory.clear(obj, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun and(obj: Any) = MockKObjectScope(obj, *objects)
}
/**
* Scope for constructor calls. Part of DSL.
*/
class MockKConstructorScope(
val type: KClass,
val recordPrivateCalls: Boolean,
val localToThread: Boolean
) : MockKUnmockKScope() {
override fun doMock(): MockKCancellation {
return MockKGateway.implementation().constructorMockFactory.constructorMockk(
type, recordPrivateCalls, localToThread
)
}
override fun clear(answers: Boolean, recordedCalls: Boolean, childMocks: Boolean) {
MockKGateway.implementation().constructorMockFactory.clear(type, MockKGateway.ClearOptions(answers, recordedCalls, childMocks))
}
}
/**
* Wraps block of code for safe resource allocation and deallocation. Part of DSL
*/
inline fun MockKUnmockKScope.use(block: () -> T): T {
mock()
return try {
block()
} finally {
unmock()
}
}
/**
* Slot allows to capture one value.
*
* If this values is lambda then it's possible to invoke it.
*/
class CapturingSlot() {
var isCaptured = false
var isNull = false
lateinit var captured: T
fun clear() {
isCaptured = false
isNull = false
}
override fun toString(): String =
"slot(${if (isCaptured) "captured=${if (isNull) "null" else captured.toStr()}" else ""})"
}
inline fun R, R> CapturingSlot.invoke() = captured.invoke()
inline fun R, R, A1> CapturingSlot.invoke(arg1: A1) = captured.invoke(arg1)
inline fun R, R, A1, A2> CapturingSlot.invoke(arg1: A1, arg2: A2) =
captured.invoke(arg1, arg2)
inline fun R, R, A1, A2, A3> CapturingSlot.invoke(arg1: A1, arg2: A2, arg3: A3) =
captured.invoke(arg1, arg2, arg3)
inline fun R, R, A1, A2, A3, A4> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4
) = captured.invoke(arg1, arg2, arg3, arg4)
inline fun R, R, A1, A2, A3, A4, A5> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5
) = captured.invoke(arg1, arg2, arg3, arg4, arg5)
inline fun R, R, A1, A2, A3, A4, A5, A6> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15
) = captured.invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16> CapturingSlot.invoke(
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
arg5: A5,
arg6: A6,
arg7: A7,
arg8: A8,
arg9: A9,
arg10: A10,
arg11: A11,
arg12: A12,
arg13: A13,
arg14: A14,
arg15: A15,
arg16: A16
) = captured.invoke(
arg1,
arg2,
arg3,
arg4,
arg5,
arg6,
arg7,
arg8,
arg9,
arg10,
arg11,
arg12,
arg13,
arg14,
arg15,
arg16
)
inline fun R, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17> CapturingSlot