diff --git a/examples/src/commonTest/kotlin/tech/antibytes/kmock/example/MockFactory.kt b/examples/src/commonTest/kotlin/tech/antibytes/kmock/example/MockFactory.kt index 6636a2a4..5d6f8e1d 100644 --- a/examples/src/commonTest/kotlin/tech/antibytes/kmock/example/MockFactory.kt +++ b/examples/src/commonTest/kotlin/tech/antibytes/kmock/example/MockFactory.kt @@ -11,6 +11,7 @@ import tech.antibytes.kmock.KMockContract internal expect inline fun kmock( verifier: KMockContract.Collector = KMockContract.Collector { _, _ -> Unit }, relaxed: Boolean = false, + relaxUnitFun: Boolean = false, freeze: Boolean = true ): T diff --git a/kmock-gradle/src/main/kotlin/tech/antibytes/gradle/kmock/FactoryGenerator.kt b/kmock-gradle/src/main/kotlin/tech/antibytes/gradle/kmock/FactoryGenerator.kt index 05782329..43c90934 100644 --- a/kmock-gradle/src/main/kotlin/tech/antibytes/gradle/kmock/FactoryGenerator.kt +++ b/kmock-gradle/src/main/kotlin/tech/antibytes/gradle/kmock/FactoryGenerator.kt @@ -30,6 +30,12 @@ internal object FactoryGenerator : KMockPluginContract.FactoryGenerator { .build() } + private fun buildUnitRelaxedParameter(): ParameterSpec { + return ParameterSpec.builder("relaxUnitFun", Boolean::class) + .defaultValue("false") + .build() + } + private fun buildVerifierParameter(): ParameterSpec { return ParameterSpec.builder("verifier", COLLECTOR_NAME) .defaultValue("Collector { _, _ -> Unit }") @@ -51,6 +57,7 @@ internal object FactoryGenerator : KMockPluginContract.FactoryGenerator { .returns(type) .addParameter(buildVerifierParameter()) .addParameter(buildRelaxedParameter()) + .addParameter(buildUnitRelaxedParameter()) .addParameter(buildFreezeParameter()) .addModifiers(KModifier.EXPECT) .build() diff --git a/kmock-gradle/src/test/kotlin/tech/antibytes/gradle/kmock/FactoryGeneratorSpec.kt b/kmock-gradle/src/test/kotlin/tech/antibytes/gradle/kmock/FactoryGeneratorSpec.kt index b8f2a48c..7b14a030 100644 --- a/kmock-gradle/src/test/kotlin/tech/antibytes/gradle/kmock/FactoryGeneratorSpec.kt +++ b/kmock-gradle/src/test/kotlin/tech/antibytes/gradle/kmock/FactoryGeneratorSpec.kt @@ -62,6 +62,8 @@ class FactoryGeneratorSpec { } } + println(actual) + actual!!.normalizeSource() mustBe expected.normalizeSource() } } diff --git a/kmock-gradle/src/test/resources/generatorTest/MockFactory.kt b/kmock-gradle/src/test/resources/generatorTest/MockFactory.kt index 8e3fe16d..12c8ce1c 100644 --- a/kmock-gradle/src/test/resources/generatorTest/MockFactory.kt +++ b/kmock-gradle/src/test/resources/generatorTest/MockFactory.kt @@ -8,6 +8,7 @@ import tech.antibytes.kmock.KMockContract.Collector internal expect inline fun kmock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, relaxed: Boolean = false, + relaxUnitFun: Boolean = false, freeze: Boolean = true ): T diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockFactoryGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockFactoryGenerator.kt index ea44937a..86dcd68e 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockFactoryGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockFactoryGenerator.kt @@ -34,6 +34,17 @@ internal class KMockFactoryGenerator( return parameter.build() } + private fun buildUnitRelaxedParameter( + isKmp: Boolean + ): ParameterSpec { + val parameter = ParameterSpec.builder("relaxUnitFun", Boolean::class) + if (!isKmp) { + parameter.defaultValue("false") + } + + return parameter.build() + } + private fun buildVerifierParameter( isKmp: Boolean ): ParameterSpec { @@ -67,24 +78,24 @@ internal class KMockFactoryGenerator( if (relaxer == null) { function.addStatement( - "%L::class -> %LMock(verifier = verifier, freeze = freeze) as T", + "%L::class -> %LMock(verifier = verifier, relaxUnitFun = relaxUnitFun, freeze = freeze) as T", qualifiedName, interfaceName, ) function.addStatement( - "%LMock::class -> %LMock(verifier = verifier, freeze = freeze) as T", + "%LMock::class -> %LMock(verifier = verifier, relaxUnitFun = relaxUnitFun, freeze = freeze) as T", interfaceName, interfaceName, ) } else { function.addStatement( - "%L::class -> %LMock(verifier = verifier, relaxed = relaxed, freeze = freeze) as T", + "%L::class -> %LMock(verifier = verifier, relaxed = relaxed, relaxUnitFun = relaxUnitFun, freeze = freeze) as T", qualifiedName, interfaceName, ) function.addStatement( - "%LMock::class -> %LMock(verifier = verifier, relaxed = relaxed, freeze = freeze) as T", + "%LMock::class -> %LMock(verifier = verifier, relaxed = relaxed, relaxUnitFun = relaxUnitFun, freeze = freeze) as T", interfaceName, interfaceName, ) @@ -109,6 +120,7 @@ internal class KMockFactoryGenerator( .returns(type) .addParameter(buildVerifierParameter(isKmp)) .addParameter(buildRelaxedParameter(isKmp)) + .addParameter(buildUnitRelaxedParameter(isKmp)) .addParameter(buildFreezeParameter(isKmp)) if (isKmp) { diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerator.kt index 618a5b04..dc905130 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerator.kt @@ -40,6 +40,7 @@ import tech.antibytes.kmock.processor.ProcessorContract.Companion.COLLECTOR_NAME import tech.antibytes.kmock.processor.ProcessorContract.Companion.KMOCK_CONTRACT import tech.antibytes.kmock.processor.ProcessorContract.Companion.PROP_NAME import tech.antibytes.kmock.processor.ProcessorContract.Companion.SYNC_FUN_NAME +import tech.antibytes.kmock.processor.ProcessorContract.Companion.UNIT_RELAXER import tech.antibytes.kmock.processor.ProcessorContract.Relaxer import java.util.Locale @@ -91,11 +92,22 @@ internal class KMockGenerator( } } - private fun buildRelaxer(relaxer: Relaxer?): String { - return if (relaxer == null) { + private fun buildRelaxers(relaxer: Relaxer?, useUnitFunRelaxer: Boolean): String { + val unitFunRelaxerStr = if (useUnitFunRelaxer) { + "unitFunRelaxer = if (relaxUnitFun) { { ${UNIT_RELAXER.simpleName}() } } else { null }" + } else { "" + } + val relaxerStr = if (relaxer != null) { + "relaxer = if (relaxed) { { mockId -> ${relaxer.functionName}(mockId) } } else { null }" + } else { + "relaxer = null" + } + + return if (unitFunRelaxerStr.isEmpty()) { + relaxerStr } else { - "relaxer = if(relaxed) { { mockId -> ${relaxer.functionName}(mockId) } } else { null }" + "$unitFunRelaxerStr, $relaxerStr" } } @@ -114,9 +126,13 @@ internal class KMockGenerator( val freeze = ParameterSpec.builder("freeze", Boolean::class) freeze.defaultValue("true") + val relaxUnit = ParameterSpec.builder("relaxUnitFun", Boolean::class) + relaxUnit.defaultValue("false") + constructor.addParameter(collector.build()) constructor.addParameter(spy.build()) constructor.addParameter(freeze.build()) + constructor.addParameter(relaxUnit.build()) if (relaxer != null) { val relaxed = ParameterSpec.builder("relaxed", Boolean::class) @@ -188,10 +204,10 @@ internal class KMockGenerator( """.trimMargin(), name, "null", - buildRelaxer(relaxer), + buildRelaxers(relaxer, false), name, "{ spyOn.$propertyName }", - buildRelaxer(relaxer) + buildRelaxers(relaxer, false) ) } else { propertyMock.initializer( @@ -206,11 +222,11 @@ internal class KMockGenerator( name, "null", "null", - buildRelaxer(relaxer), + buildRelaxers(relaxer, false), name, "{ spyOn.$propertyName }", "{ spyOn.$propertyName = it; Unit }", - buildRelaxer(relaxer) + buildRelaxers(relaxer, false) ) } } @@ -317,7 +333,7 @@ internal class KMockGenerator( mockery, "$qualifier#$mockeryName", "if (spyOn != null) { ${buildFunctionSpyInvocation(functionName, parameterNames)} } else { null }", - buildRelaxer(relaxer) + buildRelaxers(relaxer, true) ) } @@ -567,7 +583,7 @@ internal class KMockGenerator( } implementation.primaryConstructor( - buildConstructor(superType, relaxer,) + buildConstructor(superType, relaxer) ) template.getAllProperties().forEach { ksProperty -> @@ -626,6 +642,7 @@ internal class KMockGenerator( file.addImport(PROP_NAME.packageName, PROP_NAME.simpleName) file.addImport(SYNC_FUN_NAME.packageName, SYNC_FUN_NAME.simpleName) file.addImport(ASYNC_FUN_NAME.packageName, ASYNC_FUN_NAME.simpleName) + file.addImport(UNIT_RELAXER.packageName, UNIT_RELAXER.simpleName) if (relaxer != null) { file.addImport(relaxer.packageName, relaxer.functionName) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt index e76bae6f..302b447e 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt @@ -80,6 +80,11 @@ internal interface ProcessorContract { KMockContract::class.java.simpleName ) + val UNIT_RELAXER = ClassName( + KMockContract::class.java.packageName, + "relaxVoidFunction" + ) + val SYNC_FUN_NAME = ClassName( SyncFunMockery::class.java.packageName, SyncFunMockery::class.java.simpleName diff --git a/kmock-processor/src/test/resources/generatorTest/AsyncFunctionCommonExpected.kt b/kmock-processor/src/test/resources/generatorTest/AsyncFunctionCommonExpected.kt index 03685ac6..85a5591a 100644 --- a/kmock-processor/src/test/resources/generatorTest/AsyncFunctionCommonExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/AsyncFunctionCommonExpected.kt @@ -10,16 +10,19 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class AsyncFunctionCommonMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: AsyncFunctionCommon? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : AsyncFunctionCommon { public val _foo: KMockContract.AsyncFunMockery kotlin.Any> = AsyncFunMockery("generatorTest.AsyncFunctionCommon#_foo", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override suspend fun foo(fuzz: Int, ozz: Any): Any = _foo.invoke(fuzz, ozz) diff --git a/kmock-processor/src/test/resources/generatorTest/AsyncFunctionPlatformExpected.kt b/kmock-processor/src/test/resources/generatorTest/AsyncFunctionPlatformExpected.kt index af3e98b3..26eaf21a 100644 --- a/kmock-processor/src/test/resources/generatorTest/AsyncFunctionPlatformExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/AsyncFunctionPlatformExpected.kt @@ -9,16 +9,19 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class AsyncFunctionPlatformMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: AsyncFunctionPlatform? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : AsyncFunctionPlatform { public val _foo: KMockContract.AsyncFunMockery kotlin.Any> = AsyncFunMockery("generatorTest.AsyncFunctionPlatform#_foo", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override suspend fun foo(fuzz: Int, ozz: Any): Any = _foo.invoke(fuzz, ozz) diff --git a/kmock-processor/src/test/resources/generatorTest/FactoryCommonExpected.kt b/kmock-processor/src/test/resources/generatorTest/FactoryCommonExpected.kt index f6d8461c..3158a0a4 100644 --- a/kmock-processor/src/test/resources/generatorTest/FactoryCommonExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/FactoryCommonExpected.kt @@ -7,12 +7,13 @@ import tech.antibytes.kmock.KMockContract.Collector internal actual inline fun kmock( verifier: KMockContract.Collector, relaxed: Boolean, + relaxUnitFun: Boolean, freeze: Boolean ): T = when (T::class) { generatorTest.PropertyCommon::class -> generatorTest.PropertyCommonMock(verifier = verifier, - freeze = freeze) as T + relaxUnitFun = relaxUnitFun, freeze = freeze) as T generatorTest.PropertyCommonMock::class -> generatorTest.PropertyCommonMock(verifier = verifier, - freeze = freeze) as T + relaxUnitFun = relaxUnitFun, freeze = freeze) as T else -> throw RuntimeException("Unknown Interface ${T::class.simpleName}.") } diff --git a/kmock-processor/src/test/resources/generatorTest/FactoryPlatformExpected.kt b/kmock-processor/src/test/resources/generatorTest/FactoryPlatformExpected.kt index 50fcf34d..8fa052b1 100644 --- a/kmock-processor/src/test/resources/generatorTest/FactoryPlatformExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/FactoryPlatformExpected.kt @@ -7,12 +7,13 @@ import tech.antibytes.kmock.KMockContract.Collector internal inline fun kmock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, relaxed: Boolean = false, + relaxUnitFun: Boolean = false, freeze: Boolean = true ): T = when (T::class) { generatorTest.PropertyPlatform::class -> generatorTest.PropertyPlatformMock(verifier = verifier, - freeze = freeze) as T + relaxUnitFun = relaxUnitFun, freeze = freeze) as T generatorTest.PropertyPlatformMock::class -> generatorTest.PropertyPlatformMock(verifier = - verifier, freeze = freeze) as T + verifier, relaxUnitFun = relaxUnitFun, freeze = freeze) as T else -> throw RuntimeException("Unknown Interface ${T::class.simpleName}.") } diff --git a/kmock-processor/src/test/resources/generatorTest/FactoryRelaxedExpected.kt b/kmock-processor/src/test/resources/generatorTest/FactoryRelaxedExpected.kt index 7412f66c..466a6588 100644 --- a/kmock-processor/src/test/resources/generatorTest/FactoryRelaxedExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/FactoryRelaxedExpected.kt @@ -7,12 +7,13 @@ import tech.antibytes.kmock.KMockContract.Collector internal inline fun kmock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, relaxed: Boolean = false, + relaxUnitFun: Boolean = false, freeze: Boolean = true ): T = when (T::class) { generatorTest.Relaxed::class -> generatorTest.RelaxedMock(verifier = verifier, relaxed = relaxed, - freeze = freeze) as T + relaxUnitFun = relaxUnitFun, freeze = freeze) as T generatorTest.RelaxedMock::class -> generatorTest.RelaxedMock(verifier = verifier, relaxed = - relaxed, freeze = freeze) as T + relaxed, relaxUnitFun = relaxUnitFun, freeze = freeze) as T else -> throw RuntimeException("Unknown Interface ${T::class.simpleName}.") } diff --git a/kmock-processor/src/test/resources/generatorTest/FunctionOverloadExpected.kt b/kmock-processor/src/test/resources/generatorTest/FunctionOverloadExpected.kt index ffe5e30f..e0fa612e 100644 --- a/kmock-processor/src/test/resources/generatorTest/FunctionOverloadExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/FunctionOverloadExpected.kt @@ -11,71 +11,82 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class SyncFunctionOverloadMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: SyncFunctionOverload? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : SyncFunctionOverload { public override val foo: Any get() = _foo.onGet() public val _foo: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.SyncFunctionOverload#_foo", spyOnGet = null, collector = - verifier, freeze = freeze, ) + verifier, freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.SyncFunctionOverload#_foo", spyOnGet = { spyOn.foo }, - collector = verifier, freeze = freeze, ) + collector = verifier, freeze = freeze, relaxer = null) } public val _fooWithIntAny: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithIntAny", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithAnyInt: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithAnyInt", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithAnyString: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithAnyString", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithStringAny: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithStringAny", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithStringGeneratorTestAbc: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithStringGeneratorTestAbc", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithFunction1: KMockContract.SyncFunMockery) -> kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithFunction1", spyOn = if (spyOn != null) { { fuzz -> - foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithAny: KMockContract.SyncFunMockery kotlin.Unit> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithAny", spyOn = if (spyOn != null) { { fuzz -> - foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithSyncFunctionOverload: KMockContract.SyncFunMockery kotlin.Unit> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithSyncFunctionOverload", spyOn = if (spyOn != null) { { fuzz -> - foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithLPG: KMockContract.SyncFunMockery kotlin.Unit> = SyncFunMockery("generatorTest.SyncFunctionOverload#_fooWithLPG", spyOn = if (spyOn != null) { { fuzz -> - foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override fun foo(fuzz: Int, ozz: Any): Any = _fooWithIntAny.invoke(fuzz, ozz) diff --git a/kmock-processor/src/test/resources/generatorTest/GenericsExpected.kt b/kmock-processor/src/test/resources/generatorTest/GenericsExpected.kt index 994bfa46..6f40bd80 100644 --- a/kmock-processor/src/test/resources/generatorTest/GenericsExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/GenericsExpected.kt @@ -7,11 +7,13 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class GenericsMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: Generics? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : Generics { public override var template: K get() = _template.onGet() @@ -19,20 +21,22 @@ internal class GenericsMock( public val _template: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.Generics#_template", spyOnGet = null, spyOnSet = null, - collector = verifier, freeze = freeze, ) + collector = verifier, freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.Generics#_template", spyOnGet = { spyOn.template }, spyOnSet - = { spyOn.template = it; Unit }, collector = verifier, freeze = freeze, ) + = { spyOn.template = it; Unit }, collector = verifier, freeze = freeze, relaxer = null) } public val _foo: KMockContract.SyncFunMockery kotlin.Unit> = SyncFunMockery("generatorTest.Generics#_foo", spyOn = if (spyOn != null) { { payload -> - foo(payload) } } else { null }, collector = verifier, freeze = freeze, ) + foo(payload) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public val _fooWithInt: KMockContract.SyncFunMockery kotlin.Unit> = SyncFunMockery("generatorTest.Generics#_fooWithInt", spyOn = if (spyOn != null) { { payload -> - foo(payload) } } else { null }, collector = verifier, freeze = freeze, ) + foo(payload) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override fun foo(payload: T): Unit = _foo.invoke(payload) diff --git a/kmock-processor/src/test/resources/generatorTest/PropertyCommonExpected.kt b/kmock-processor/src/test/resources/generatorTest/PropertyCommonExpected.kt index 9221757a..97cb7e3b 100644 --- a/kmock-processor/src/test/resources/generatorTest/PropertyCommonExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/PropertyCommonExpected.kt @@ -10,21 +10,23 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class PropertyCommonMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: PropertyCommon? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : PropertyCommon { public override val foo: String get() = _foo.onGet() public val _foo: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.PropertyCommon#_foo", spyOnGet = null, collector = verifier, - freeze = freeze, ) + freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.PropertyCommon#_foo", spyOnGet = { spyOn.foo }, collector = - verifier, freeze = freeze, ) + verifier, freeze = freeze, relaxer = null) } @@ -34,10 +36,10 @@ internal class PropertyCommonMock( public val _buzz: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.PropertyCommon#_buzz", spyOnGet = null, spyOnSet = null, - collector = verifier, freeze = freeze, ) + collector = verifier, freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.PropertyCommon#_buzz", spyOnGet = { spyOn.buzz }, spyOnSet = - { spyOn.buzz = it; Unit }, collector = verifier, freeze = freeze, ) + { spyOn.buzz = it; Unit }, collector = verifier, freeze = freeze, relaxer = null) } diff --git a/kmock-processor/src/test/resources/generatorTest/PropertyPlatformExpected.kt b/kmock-processor/src/test/resources/generatorTest/PropertyPlatformExpected.kt index 1e5d4c1e..a69e3b27 100644 --- a/kmock-processor/src/test/resources/generatorTest/PropertyPlatformExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/PropertyPlatformExpected.kt @@ -9,21 +9,23 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class PropertyPlatformMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: PropertyPlatform? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : PropertyPlatform { public override val foo: String get() = _foo.onGet() - public val _foo: KMockContract.PropertyMockery = if(spyOn == null) { + public val _foo: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.PropertyPlatform#_foo", spyOnGet = null, collector = - verifier, freeze = freeze, ) + verifier, freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.PropertyPlatform#_foo", spyOnGet = { spyOn.foo }, collector - = verifier, freeze = freeze, ) + = verifier, freeze = freeze, relaxer = null) } @@ -31,12 +33,12 @@ internal class PropertyPlatformMock( get() = _buzz.onGet() set(`value`) = _buzz.onSet(value) - public val _buzz: KMockContract.PropertyMockery = if(spyOn == null) { + public val _buzz: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.PropertyPlatform#_buzz", spyOnGet = null, spyOnSet = null, - collector = verifier, freeze = freeze, ) + collector = verifier, freeze = freeze, relaxer = null) } else { PropertyMockery("generatorTest.PropertyPlatform#_buzz", spyOnGet = { spyOn.buzz }, spyOnSet - = { spyOn.buzz = it; Unit }, collector = verifier, freeze = freeze, ) + = { spyOn.buzz = it; Unit }, collector = verifier, freeze = freeze, relaxer = null) } diff --git a/kmock-processor/src/test/resources/generatorTest/RelaxedExpected.kt b/kmock-processor/src/test/resources/generatorTest/RelaxedExpected.kt index 092da0d5..1d07fc56 100644 --- a/kmock-processor/src/test/resources/generatorTest/RelaxedExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/RelaxedExpected.kt @@ -10,11 +10,13 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class RelaxedMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: Relaxed? = null, freeze: Boolean = true, + relaxUnitFun: Boolean = false, relaxed: Boolean = false ) : Relaxed { public override val buzz: String @@ -22,23 +24,25 @@ internal class RelaxedMock( public val _buzz: KMockContract.PropertyMockery = if (spyOn == null) { PropertyMockery("generatorTest.Relaxed#_buzz", spyOnGet = null, collector = verifier, - freeze = freeze, relaxer = if(relaxed) { { mockId -> relaxed(mockId) } } else { null }) + freeze = freeze, relaxer = if (relaxed) { { mockId -> relaxed(mockId) } } else { null }) } else { PropertyMockery("generatorTest.Relaxed#_buzz", spyOnGet = { spyOn.buzz }, collector = - verifier, freeze = freeze, relaxer = if(relaxed) { { mockId -> relaxed(mockId) } } else { + verifier, freeze = freeze, relaxer = if (relaxed) { { mockId -> relaxed(mockId) } } else { null }) } public val _foo: KMockContract.SyncFunMockery kotlin.String> = SyncFunMockery("generatorTest.Relaxed#_foo", spyOn = if (spyOn != null) { { payload -> - foo(payload) } } else { null }, collector = verifier, freeze = freeze, relaxer = if(relaxed) - { { mockId -> relaxed(mockId) } } else { null }) + foo(payload) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = if (relaxed) { { + mockId -> relaxed(mockId) } } else { null }) public val _bar: KMockContract.AsyncFunMockery kotlin.String> = AsyncFunMockery("generatorTest.Relaxed#_bar", spyOn = if (spyOn != null) { { payload -> - bar(payload) } } else { null }, collector = verifier, freeze = freeze, relaxer = if(relaxed) - { { mockId -> relaxed(mockId) } } else { null }) + bar(payload) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = if (relaxed) { { + mockId -> relaxed(mockId) } } else { null }) public override fun foo(payload: Any): String = _foo.invoke(payload) diff --git a/kmock-processor/src/test/resources/generatorTest/SyncFunctionCommonExpected.kt b/kmock-processor/src/test/resources/generatorTest/SyncFunctionCommonExpected.kt index 197ce2c8..6ecfef80 100644 --- a/kmock-processor/src/test/resources/generatorTest/SyncFunctionCommonExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/SyncFunctionCommonExpected.kt @@ -10,16 +10,19 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class SyncFunctionCommonMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: SyncFunctionCommon? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : SyncFunctionCommon { public val _foo: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionCommon#_foo", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override fun foo(fuzz: Int, ozz: Any): Any = _foo.invoke(fuzz, ozz) diff --git a/kmock-processor/src/test/resources/generatorTest/SyncFunctionPlatformExpected.kt b/kmock-processor/src/test/resources/generatorTest/SyncFunctionPlatformExpected.kt index 544c6d50..ab5a007f 100644 --- a/kmock-processor/src/test/resources/generatorTest/SyncFunctionPlatformExpected.kt +++ b/kmock-processor/src/test/resources/generatorTest/SyncFunctionPlatformExpected.kt @@ -9,16 +9,19 @@ import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.kmock.PropertyMockery import tech.antibytes.kmock.SyncFunMockery +import tech.antibytes.kmock.relaxVoidFunction internal class SyncFunctionPlatformMock( verifier: KMockContract.Collector = Collector { _, _ -> Unit }, spyOn: SyncFunctionPlatform? = null, - freeze: Boolean = true + freeze: Boolean = true, + relaxUnitFun: Boolean = false ) : SyncFunctionPlatform { public val _foo: KMockContract.SyncFunMockery kotlin.Any> = SyncFunMockery("generatorTest.SyncFunctionPlatform#_foo", spyOn = if (spyOn != null) { { fuzz, ozz -> - foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, ) + foo(fuzz, ozz) } } else { null }, collector = verifier, freeze = freeze, unitFunRelaxer = if + (relaxUnitFun) { { relaxVoidFunction() } } else { null }, relaxer = null) public override fun foo(fuzz: Int, ozz: Any): Any = _foo.invoke(fuzz, ozz) diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/AsyncFunMockery.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/AsyncFunMockery.kt index db0c7cf8..de158494 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/AsyncFunMockery.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/AsyncFunMockery.kt @@ -13,10 +13,18 @@ class AsyncFunMockery>( id: String, collector: Collector = Collector { _, _ -> Unit }, relaxer: Relaxer? = null, + unitFunRelaxer: Relaxer? = null, freeze: Boolean = true, spyOn: SideEffect? = null ) : KMockContract.AsyncFunMockery, - FunMockery(id, collector, relaxer, freeze, spyOn) { + FunMockery( + id = id, + collector = collector, + relaxer = relaxer, + unitFunRelaxer = unitFunRelaxer, + freeze = freeze, + spyOn = spyOn + ) { private suspend fun execute( function: suspend () -> ReturnValue, spy: (suspend () -> ReturnValue)?, diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/FunMockery.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/FunMockery.kt index 3cc198a7..35c678c0 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/FunMockery.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/FunMockery.kt @@ -21,6 +21,7 @@ abstract class FunMockery>( override val id: String, collector: Collector = Collector { _, _ -> Unit }, relaxer: Relaxer?, + unitFunRelaxer: Relaxer?, private val freeze: Boolean, protected val spyOn: SideEffect? ) : KMockContract.FunMockery { @@ -46,6 +47,8 @@ abstract class FunMockery>( private val arguments: IsoMutableList?> = sharedMutableListOf() private val relaxer: AtomicRef?> = atomic(relaxer) + private val unitFunRelaxer: AtomicRef?> = atomic(unitFunRelaxer) + private val _verificationBuilder: AtomicRef = atomic(null) override var verificationBuilderReference: KMockContract.VerificationChainBuilder? by _verificationBuilder @@ -170,7 +173,8 @@ abstract class FunMockery>( } protected fun invokeRelaxerOrFail(): ReturnValue { - return relaxer.value?.relax(id) + return unitFunRelaxer.value?.relax(id) + ?: relaxer.value?.relax(id) ?: throw MockError.MissingStub("Missing stub value for $id") } diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/SyncFunMockery.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/SyncFunMockery.kt index fbc612f2..bf9a8bb5 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/SyncFunMockery.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/SyncFunMockery.kt @@ -13,10 +13,18 @@ class SyncFunMockery>( id: String, collector: Collector = Collector { _, _ -> Unit }, relaxer: Relaxer? = null, + unitFunRelaxer: Relaxer? = null, freeze: Boolean = true, spyOn: SideEffect? = null ) : KMockContract.SyncFunMockery, - FunMockery(id, collector, relaxer, freeze, spyOn) { + FunMockery( + id = id, + collector = collector, + relaxer = relaxer, + unitFunRelaxer = unitFunRelaxer, + freeze = freeze, + spyOn = spyOn + ) { private fun execute( function: () -> ReturnValue, spy: (() -> ReturnValue)?, diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/UnitFunRelaxer.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/UnitFunRelaxer.kt new file mode 100644 index 00000000..5b2cba59 --- /dev/null +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/UnitFunRelaxer.kt @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package tech.antibytes.kmock + +inline fun relaxVoidFunction(): T? { + return if (T::class == Unit::class) { + Unit as T + } else { + null + } +} diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockerySpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockerySpec.kt index 3d6377ae..8e861209 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockerySpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockerySpec.kt @@ -191,6 +191,32 @@ class AsyncFunMockerySpec { @Test @JsName("fn6b") + fun `Given invoke is called it uses the given UnitFunRelaxer if no ReturnValue Provider is set`(): AsyncTestReturnValue { + // Given + val name: String = fixture.fixture() + val value = AtomicReference(fixture.fixture()) + val capturedId = AtomicReference(null) + val mockery = SyncFunMockery Unit>( + name, + unitFunRelaxer = { givenId -> + capturedId.set(givenId) + + value + } + ) + + return runBlockingTestInContext(testScope1.coroutineContext) { + // When + val actual = mockery.invoke() + + // Then + actual mustBe value + capturedId.value mustBe name + } + } + + @Test + @JsName("fn6c") fun `Given invoke is called it uses the given Implementation if no ReturnValue Provider is set`(): AsyncTestReturnValue { // Given val name: String = fixture.fixture() diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockeryUnfrozenSpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockeryUnfrozenSpec.kt index 4ec5c270..9ca4271d 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockeryUnfrozenSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/AsyncFunMockeryUnfrozenSpec.kt @@ -12,6 +12,7 @@ import tech.antibytes.kmock.KMockContract.Collector import tech.antibytes.util.test.MockError import tech.antibytes.util.test.annotations.IgnoreJs import tech.antibytes.util.test.annotations.JsOnly +import tech.antibytes.util.test.coroutine.AsyncTestReturnValue import tech.antibytes.util.test.coroutine.runBlockingTest import tech.antibytes.util.test.fixture.fixture import tech.antibytes.util.test.fixture.kotlinFixture @@ -138,6 +139,30 @@ class AsyncFunMockeryUnfrozenSpec { @Test @JsName("fn6b") + fun `Given invoke is called it uses the given UnitFunRelaxer if no ReturnValue Provider is set`(): AsyncTestReturnValue = runBlockingTest { + // Given + val name: String = fixture.fixture() + val value = AtomicReference(fixture.fixture()) + val capturedId = AtomicReference(null) + val mockery = AsyncFunMockery Unit>( + name, + unitFunRelaxer = { givenId -> + capturedId.set(givenId) + + value + } + ) + + // When + val actual = mockery.invoke() + + // Then + actual mustBe value + capturedId.value mustBe name + } + + @Test + @JsName("fn6c") fun `Given invoke is called it uses the given Implementation if no ReturnValue Provider is set`() = runBlockingTest { // Given val name: String = fixture.fixture() diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockerySpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockerySpec.kt index e96df943..8047e95c 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockerySpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockerySpec.kt @@ -193,6 +193,32 @@ class SyncFunMockerySpec { @Test @JsName("fn6b") + fun `Given invoke is called it uses the given UnitFunRelaxer if no ReturnValue Provider is set`(): AsyncTestReturnValue { + // Given + val name: String = fixture.fixture() + val value = AtomicReference(fixture.fixture()) + val capturedId = AtomicReference(null) + val mockery = AsyncFunMockery Unit>( + name, + unitFunRelaxer = { givenId -> + capturedId.set(givenId) + + value + } + ) + + return runBlockingTestInContext(testScope1.coroutineContext) { + // When + val actual = mockery.invoke() + + // Then + actual mustBe value + capturedId.value mustBe name + } + } + + @Test + @JsName("fn6c") fun `Given invoke is called it uses the given Implementation if no ReturnValue Provider is set`(): AsyncTestReturnValue { // Given val name: String = fixture.fixture() diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockeryUnfrozenSpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockeryUnfrozenSpec.kt index 5cd57169..426e7a84 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockeryUnfrozenSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/SyncFunMockeryUnfrozenSpec.kt @@ -159,6 +159,30 @@ class SyncFunMockeryUnfrozenSpec { @Test @JsName("fn6b") + fun `Given invoke is called it uses the given UnitFunRelaxer if no ReturnValue Provider is set`() { + // Given + val name: String = fixture.fixture() + val value = AtomicReference(fixture.fixture()) + val capturedId = AtomicReference(null) + val mockery = SyncFunMockery Unit>( + name, + unitFunRelaxer = { givenId -> + capturedId.set(givenId) + + value + } + ) + + // When + val actual = mockery.invoke() + + // Then + actual mustBe value + capturedId.value mustBe name + } + + @Test + @JsName("fn6c") fun `Given invoke is called it uses the given Implementation if no ReturnValue Provider is set`() { // Given val name: String = fixture.fixture() diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/UnitFunRelaxerSpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/UnitFunRelaxerSpec.kt new file mode 100644 index 00000000..9a189c7a --- /dev/null +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/UnitFunRelaxerSpec.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package tech.antibytes.kmock + +import tech.antibytes.util.test.mustBe +import kotlin.js.JsName +import kotlin.test.Test + +class UnitFunRelaxerSpec { + @Test + @JsName("fn0") + fun `Given relaxVoidFunction is called it returns Unit if the refered type is Unit`() { + relaxVoidFunction() mustBe Unit + } + + @Test + @JsName("fn1") + fun `Given relaxVoidFunction is called it returns Null if the refered type is not Unit`() { + relaxVoidFunction() mustBe null + } +}