Add mocking for suspend functions
dalewking opened this issue · 2 comments
dalewking commented
The mocking for functional types is great, but you seem to have left out mocking for suspend functions. I should be able to say
val callback: suspend (User) -> Unit = mockSuspendFunction1(mocker)
dalewking commented
I created function mocking support on top of Mockative and one of the useful features to have is a way to tell mock suspend function to block its return until you tell it to resume later. This is useful for testing for example that a loading status is true while a bit of code has not returned yet.
dalewking commented
Ignoring my comment about pausing (which i can handle in different ways) this should probably work:
@PublishedApi
internal class Anonymous()
public fun methodName(vararg paramTypes: String) =
"invoke(${paramTypes.joinToString(", ")})"
public suspend fun <R> mockSuspendFunction0(
mocker: Mocker,
block: (suspend () -> R)? = null,
): suspend () -> R =
Anonymous().let { rec ->
suspend {
mocker.registerSuspend<R>(rec, "invoke()")
}
}.also {
if (block != null) mocker.everySuspending { it() } runs { block() }
}
public suspend inline fun <R, reified A1>
mockSuspendFunction1(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1) -> R)? = null,
): suspend (A1) -> R {
val instance = Anonymous()
val function: suspend (A1) -> R =
{ a1: A1 ->
mocker.registerSuspend(instance, methodName, a1)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny()) } runs { block(it[0] as A1) }
}
}
public suspend inline fun <R, reified A1, reified A2>
mockSuspendFunction2(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2) -> R)? = null,
): suspend (A1, A2) -> R {
val rec = Anonymous()
val function: suspend (A1, A2) -> R =
{ a1: A1, a2: A2 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3>
mockSuspendFunction3(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3) -> R)? = null,
): suspend (A1, A2, A3) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3) -> R =
{ a1: A1, a2: A2, a3: A3 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4>
mockSuspendFunction4(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4) -> R)? = null,
): suspend (A1, A2, A3, A4) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5>
mockSuspendFunction5(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5) -> R)? = null,
): suspend (A1, A2, A3, A4, A5) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6>
mockSuspendFunction6(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5, A6) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5, A6) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5, a6)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5, it[5] as A6) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7>
mockSuspendFunction7(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5, A6, A7) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5, a6, a7)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5, it[5] as A6, it[6] as A7) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8>
mockSuspendFunction8(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5, A6, A7, A8) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5, a6, a7, a8)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5, it[5] as A6, it[6] as A7, it[7] as A8) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8, reified A9>
mockSuspendFunction9(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8, a9: A9 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5, a6, a7, a8, a9)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5, it[5] as A6, it[6] as A7, it[7] as A8, it[8] as A9) }
}
}
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8, reified A9, reified A10>
mockSuspendFunction10(
mocker: Mocker,
methodName: String,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R {
val rec = Anonymous()
val function: suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R =
{ a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8, a9: A9, a10: A10 ->
mocker.registerSuspend<R>(rec, methodName, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
}
return function.also {
if (block != null) mocker.everySuspending { it(isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny(), isAny()) } runs { block(it[0] as A1, it[1] as A2, it[2] as A3, it[3] as A4, it[4] as A5, it[5] as A6, it[6] as A7, it[7] as A8, it[8] as A9, it[9] as A10) }
}
}
public suspend inline fun <R, reified A1>
mockSuspendFunction1(
mocker: Mocker,
noinline block: (suspend (A1) -> R)? = null,
): suspend (A1) -> R =
mockSuspendFunction1(mocker, methodName(A1::class.bestName()), block)
public suspend inline fun <R, reified A1, reified A2>
mockSuspendFunction2(
mocker: Mocker,
noinline block: (suspend (A1, A2) -> R)? = null,
): suspend (A1, A2) -> R =
mockSuspendFunction2(
mocker,
methodName(A1::class.bestName(), A2::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3>
mockSuspendFunction3(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3) -> R)? = null,
): suspend (A1, A2, A3) -> R =
mockSuspendFunction3(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4>
mockSuspendFunction4(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4) -> R)? = null,
): suspend (A1, A2, A3, A4) -> R =
mockSuspendFunction4(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5>
mockSuspendFunction5(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5) -> R)? = null,
): suspend (A1, A2, A3, A4, A5) -> R =
mockSuspendFunction5(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6>
mockSuspendFunction6(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5, A6) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6) -> R =
mockSuspendFunction6(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName(), A6::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7>
mockSuspendFunction7(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7) -> R =
mockSuspendFunction7(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName(), A6::class.bestName(), A7::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8>
mockSuspendFunction8(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8) -> R =
mockSuspendFunction8(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName(), A6::class.bestName(), A7::class.bestName(), A8::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8, reified A9>
mockSuspendFunction9(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R =
mockSuspendFunction9(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName(), A6::class.bestName(), A7::class.bestName(), A8::class.bestName(), A9::class.bestName()),
block,
)
public suspend inline fun <R, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified A7, reified A8, reified A9, reified A10>
mockSuspendFunction10(
mocker: Mocker,
noinline block: (suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R)? = null,
): suspend (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R =
mockSuspendFunction10(
mocker,
methodName(A1::class.bestName(), A2::class.bestName(), A3::class.bestName(), A4::class.bestName(), A5::class.bestName(), A6::class.bestName(), A7::class.bestName(), A8::class.bestName(), A9::class.bestName(), A10::class.bestName()),
block,
)