diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index ae01aee5..232e1037 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -30,6 +30,7 @@ toc::[] === Added * `or` ArgumentConstraint +* `not` ArgumentConstraint * `spiesOnly` in the Gradle extension, in order to tell the processor to only create `kspy`, while adding all known mocks * `vararg` is now supported by Mocks * `freezeOnDefault` in the Gradle extension, which sets a default freeze value for `kspy` and `kmock` @@ -38,6 +39,7 @@ toc::[] * `allowInterfaces`, which combines `allowInterfacesOnKmock` and `allowInterfacesOnKspy` * `disableFactories` in order to disable the generation of `kmock` and `kspy` if needed * `customAnnotationsForMeta` to provide a hook for the usage of customized annotation for meta/shared sources +* `assertOrder` in order to make the names more consistent === Changed @@ -45,10 +47,12 @@ toc::[] * Mutable properties of Proxies now separate froze/unfrozen state is cleaner to improve Runtime * `kmock` and `kspy` are using now a shared function to improve compile time * Non intrusive behaviour (spy & relaxation) is now resolved by proxy invocation rather then by proxy initialisation in order to cover edge cases +* Assertion-/VerificationChain is not coupled any longer directly to proxies and provide improved error messages === Deprecated * `uselessPrefixes` in the Gradle Extension +* `verifyStrictOrder` use `assertOrder` === Removed @@ -67,6 +71,7 @@ toc::[] * KotlinPoet 1.10.2 -> 1.11.0 * Gradle 7.4.1 -> 7.4.2 +* Android Gradle Plugin 7.1.2 -> 7.1.3 == https://github.com/bitPogo/kmock/compare/v0.1.0\...v0.1.1[0.1.1] diff --git a/gradle.properties b/gradle.properties index ba12092d..db136e0e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ # Gradle org.gradle.jvmargs=-Xmx2048m -org.gradle.parallel=true +org.gradle.parallel=false org.gradle.dependency.verification.console=verbose # Kotlin kotlin.incremental.multiplatform=true diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt index 4fe20793..dfa0d194 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt @@ -374,7 +374,7 @@ object KMockContract { */ interface FunProxy> : Proxy> { /** - * Marks the proxy as ignore during verification (e.g. build-in methods). Meant for internal usage only! + * Marks the proxy as ignore during verification (e.g. build-in methods). Intended for internal usage only! */ val ignorableForVerification: Boolean @@ -1050,7 +1050,7 @@ object KMockContract { */ fun interface Collector { /** - * Collects a invocation of a Proxy. Meant for internal use only. + * Collects a invocation of a Proxy. Intended for internal use only. * @param referredProxy the proxy it is referring to. * @param referredCall the invocation index of the Proxy it refers to. * @suppress @@ -1060,7 +1060,7 @@ object KMockContract { /** * Handle with the aggregated information of a Proxy invocation. - * Meant for internal usage only! + * Intended for internal usage only! * @author Matthias Geisler */ interface Expectation { @@ -1094,23 +1094,27 @@ object KMockContract { } /** - * + * Wrapper for Arguments-Constraints */ internal interface ArgumentConstraintWrapper { /** - * + * Wraps a arbitrary value to eq-Constraint if it is not a Arguments-Constraints. + * @param value a arbitrary value. + * @return ArgumentConstraint */ fun wrapValue(value: Any?): ArgumentConstraint /** - * + * Wraps a arbitrary value to eq-Constraint if it is not a Arguments-Constraints and wraps that into a not-Constraint. + * @param value a arbitrary value. + * @return ArgumentConstraint the resulting not-Constraint. */ fun wrapNegatedValue(value: Any?): ArgumentConstraint } /** * Reference to a Proxy invocation. - * Meant for internal usage only! + * Intended for internal usage only! * @author Matthias Geisler */ data class Reference( @@ -1126,11 +1130,15 @@ object KMockContract { ) /** - * + * Internal Executor of Assertions. + * @author Matthias Geisler */ internal interface Assertions { /** - * + * Asserts that a FunProxy was called. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @throws AssertionError if the assertion fails. */ fun hasBeenCalledAtIndex( proxy: FunProxy<*, *>, @@ -1138,7 +1146,10 @@ object KMockContract { ) /** - * + * Asserts that a FunProxy was called without any parameter. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @throws AssertionError if the assertion fails. */ fun hasBeenCalledWithVoidAtIndex( proxy: FunProxy<*, *>, @@ -1146,7 +1157,12 @@ object KMockContract { ) /** - * + * Asserts that a FunProxy was called with n-parameter. + * The arguments do not need to be complete. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @param arguments the expected arguments. + * @throws AssertionError if the assertion fails */ fun hasBeenCalledWithAtIndex( proxy: FunProxy<*, *>, @@ -1155,7 +1171,12 @@ object KMockContract { ) /** - * + * Asserts that a FunProxy was called with n-parameter. + * The arguments must be complete. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @param arguments the expected arguments. + * @throws AssertionError if the assertion fails */ fun hasBeenStrictlyCalledWithAtIndex( proxy: FunProxy<*, *>, @@ -1164,7 +1185,12 @@ object KMockContract { ) /** - * + * Asserts that a FunProxy was without called n-parameter. + * The arguments do not need to be complete. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @param illegal the forbidden arguments. + * @throws AssertionError if the assertion fails */ fun hasBeenCalledWithoutAtIndex( proxy: FunProxy<*, *>, @@ -1173,7 +1199,10 @@ object KMockContract { ) /** - * + * Asserts that a PropertyProxy was invoked as a Getter. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @throws AssertionError if the assertion fails. */ fun wasGottenAtIndex( proxy: PropertyProxy<*>, @@ -1181,7 +1210,10 @@ object KMockContract { ) /** - * + * Asserts that a PropertyProxy was invoked as a Setter. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @throws AssertionError if the assertion fails. */ fun wasSetAtIndex( proxy: PropertyProxy<*>, @@ -1189,7 +1221,11 @@ object KMockContract { ) /** - * + * Asserts that a PropertyProxy was invoked as a Setter with a given value. + * @param proxy the actual proxy. + * @param callIndex the index of the invocation from the proxy. + * @param value the expected value. + * @throws AssertionError if the assertion fails. */ fun wasSetToAtIndex( proxy: PropertyProxy<*>, @@ -1199,46 +1235,63 @@ object KMockContract { } /** - * + * Provider for Assertion. + * @author Matthias Geisler */ interface AssertionContext { /** - * + * Asserts that a FunProxy was called. + * @throws AssertionError if the assertion fails. */ fun FunProxy<*, *>.hasBeenCalled() /** - * + * Asserts that a FunProxy was called without any parameter. + * @throws AssertionError if the assertion fails. */ fun FunProxy<*, *>.hasBeenCalledWithVoid() /** - * + * Asserts that a FunProxy was called with n-parameter. + * The arguments do not need to be complete. + * @param arguments the expected arguments. + * @throws AssertionError if the assertion fails */ fun FunProxy<*, *>.hasBeenCalledWith(vararg arguments: Any?) /** - * + * Asserts that a FunProxy was called with n-parameter. + * The arguments must be complete. + * @param arguments the expected arguments. + * @throws AssertionError if the assertion fails */ fun FunProxy<*, *>.hasBeenStrictlyCalledWith(vararg arguments: Any?) /** - * + * Asserts that a FunProxy was without called n-parameter. + * The arguments do not need to be complete. + * @param proxy the actual proxy. + * @param illegal the forbidden arguments. + * @throws AssertionError if the assertion fails */ fun FunProxy<*, *>.hasBeenCalledWithout(vararg illegal: Any?) /** - * + * Asserts that a PropertyProxy was invoked as a Getter. + * @throws AssertionError if the assertion fails. */ fun PropertyProxy<*>.wasGotten() /** - * + * Asserts that a PropertyProxy was invoked as a Setter. + * @throws AssertionError if the assertion fails. */ fun PropertyProxy<*>.wasSet() /** - * + * Asserts that a PropertyProxy was invoked as a Setter with a given value. + * @param value the expected value. + * @throws AssertionError if the assertion fails. */ fun PropertyProxy<*>.wasSetTo(value: Any?) } @@ -1256,16 +1309,18 @@ object KMockContract { } /** - * + * Combination of AssertionInsurance and AssertionContext + * @see AssertionInsurance + * @see AssertionContext */ - interface Assert : AssertionInsurance, AssertionContext + interface ChainedAssertion : AssertionInsurance, AssertionContext /** * AssertionChain in order to verify over multiple Handles. - * Meant for internal purpose only! + * Intended for internal purpose only! * @author Matthias Geisler */ - interface AssertionChain { + internal interface AssertionChain { /** * Ensures that all expected or actual values are covered depending on the context. * @throws AssertionError if the context needs to be exhaustive and not all expected or actual values are covered. @@ -1292,8 +1347,6 @@ object KMockContract { internal const val CALL_NOT_FOUND = "Expected %0 to be invoked, but no further calls were captured." internal const val STRICT_CALL_NOT_MATCH = "Expected %0 to be invoked, but %1 was called." - internal const val STRICT_CALL_IDX_NOT_FOUND = "Expected %0th call of %1 was not made." - internal const val STRICT_CALL_IDX_NOT_MATCH = "Expected %0th call of %1, but it refers to the %2th call." internal const val STRICT_MISSING_EXPECTATION = "The given verification chain covers %0 items, but only %1 were expected (%2 were referenced)." internal const val MISSING_INVOCATION = "Expected %0th call of %1 was not made." @@ -1306,8 +1359,6 @@ object KMockContract { internal const val NOT_GET = "Expected a getter and got a setter." internal const val NOT_SET = "Expected a setter and got a getter." - internal const val NON_STRICT_CALL_NOT_FOUND = "Expected %0 to be invoked, but no call was captured with the given arguments." - internal const val NOT_CALLED = "Call not found." internal const val TOO_LESS_CALLS = "Expected at least %0 calls, but found only %1." internal const val TOO_MANY_CALLS = "Expected at most %0 calls, but exceeded with %1." diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt index eb19cc9e..194546f8 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt @@ -7,11 +7,13 @@ package tech.antibytes.kmock.verification import kotlinx.atomicfu.atomic -import tech.antibytes.kmock.KMockContract -import tech.antibytes.kmock.KMockContract.Assert import tech.antibytes.kmock.KMockContract.AssertionChain import tech.antibytes.kmock.KMockContract.Assertions import tech.antibytes.kmock.KMockContract.CALL_NOT_FOUND +import tech.antibytes.kmock.KMockContract.ChainedAssertion +import tech.antibytes.kmock.KMockContract.FunProxy +import tech.antibytes.kmock.KMockContract.NOT_PART_OF_CHAIN +import tech.antibytes.kmock.KMockContract.PropertyProxy import tech.antibytes.kmock.KMockContract.Proxy import tech.antibytes.kmock.KMockContract.Reference import tech.antibytes.kmock.KMockContract.STRICT_CALL_NOT_MATCH @@ -21,7 +23,7 @@ import tech.antibytes.kmock.util.format internal class AssertionChain( private val references: List, private val assertions: Assertions = Assertions -) : AssertionChain, Assert { +) : AssertionChain, ChainedAssertion { private val invocation = atomic(0) private fun getProxyIdSet(): Set { @@ -37,7 +39,7 @@ internal class AssertionChain( proxies.forEach { proxy -> if (proxy.id !in actual) { - throw IllegalStateException(KMockContract.NOT_PART_OF_CHAIN.format(proxy.id)) + throw IllegalStateException(NOT_PART_OF_CHAIN.format(proxy.id)) } } } @@ -68,19 +70,19 @@ internal class AssertionChain( invocation.incrementAndGet() } - override fun KMockContract.FunProxy<*, *>.hasBeenCalled() { + override fun FunProxy<*, *>.hasBeenCalled() { runAssertion(this) { callIndex -> assertions.hasBeenCalledAtIndex(this, callIndex) } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWithVoid() { + override fun FunProxy<*, *>.hasBeenCalledWithVoid() { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithVoidAtIndex(this, callIndex) } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWith(vararg arguments: Any?) { + override fun FunProxy<*, *>.hasBeenCalledWith(vararg arguments: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithAtIndex( proxy = this, @@ -90,7 +92,7 @@ internal class AssertionChain( } } - override fun KMockContract.FunProxy<*, *>.hasBeenStrictlyCalledWith(vararg arguments: Any?) { + override fun FunProxy<*, *>.hasBeenStrictlyCalledWith(vararg arguments: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenStrictlyCalledWithAtIndex( proxy = this, @@ -100,7 +102,7 @@ internal class AssertionChain( } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWithout(vararg illegal: Any?) { + override fun FunProxy<*, *>.hasBeenCalledWithout(vararg illegal: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithoutAtIndex( proxy = this, @@ -110,19 +112,19 @@ internal class AssertionChain( } } - override fun KMockContract.PropertyProxy<*>.wasGotten() { + override fun PropertyProxy<*>.wasGotten() { runAssertion(this) { callIndex -> assertions.wasGottenAtIndex(proxy = this, callIndex = callIndex) } } - override fun KMockContract.PropertyProxy<*>.wasSet() { + override fun PropertyProxy<*>.wasSet() { runAssertion(this) { callIndex -> assertions.wasSetAtIndex(proxy = this, callIndex = callIndex) } } - override fun KMockContract.PropertyProxy<*>.wasSetTo(value: Any?) { + override fun PropertyProxy<*>.wasSetTo(value: Any?) { runAssertion(this) { callIndex -> assertions.wasSetToAtIndex( proxy = this, diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/Verification.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/Verification.kt index 9c362e5b..7ded9b9d 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/Verification.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/Verification.kt @@ -7,10 +7,10 @@ package tech.antibytes.kmock.verification import tech.antibytes.kmock.KMockContract -import tech.antibytes.kmock.KMockContract.Assert import tech.antibytes.kmock.KMockContract.Asserter import tech.antibytes.kmock.KMockContract.AssertionContext import tech.antibytes.kmock.KMockContract.AssertionInsurance +import tech.antibytes.kmock.KMockContract.ChainedAssertion import tech.antibytes.kmock.KMockContract.Expectation import tech.antibytes.kmock.KMockContract.NOT_CALLED import tech.antibytes.kmock.KMockContract.TOO_LESS_CALLS @@ -81,8 +81,8 @@ fun verify( fun runAssertion( chain: T, - scope: Assert.() -> Any -) where T : Assert, T : KMockContract.AssertionChain { + scope: ChainedAssertion.() -> Any +) where T : ChainedAssertion, T : KMockContract.AssertionChain { scope(chain) chain.ensureAllReferencesAreEvaluated() @@ -96,7 +96,7 @@ fun runAssertion( * @see AssertionContext * @author Matthias Geisler */ -fun Asserter.assertOrder(scope: Assert.() -> Any) = runAssertion(AssertionChain(references), scope) +fun Asserter.assertOrder(scope: ChainedAssertion.() -> Any) = runAssertion(AssertionChain(references), scope) /** * Alias of assertOrder. @@ -105,7 +105,11 @@ fun Asserter.assertOrder(scope: Assert.() -> Any) = runAssertion(AssertionChain( * @see assertOrder * @author Matthias Geisler */ -fun Asserter.verifyStrictOrder(scope: Assert.() -> Any) = assertOrder(scope) +@Deprecated( + "This will be removed with version 1.0. Use assertOrder instead.", + ReplaceWith("assertOrder(scope)") +) +fun Asserter.verifyStrictOrder(scope: ChainedAssertion.() -> Any) = assertOrder(scope) /** * Verifies a chain of Expectations. Each Expectations must be in order but gaps are allowed. diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt index 53c6e3a8..74d7dade 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt @@ -8,11 +8,13 @@ package tech.antibytes.kmock.verification import kotlinx.atomicfu.atomic import kotlinx.atomicfu.update -import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.AssertionChain import tech.antibytes.kmock.KMockContract.Assertions import tech.antibytes.kmock.KMockContract.CALL_NOT_FOUND +import tech.antibytes.kmock.KMockContract.ChainedAssertion +import tech.antibytes.kmock.KMockContract.FunProxy import tech.antibytes.kmock.KMockContract.NOT_PART_OF_CHAIN +import tech.antibytes.kmock.KMockContract.PropertyProxy import tech.antibytes.kmock.KMockContract.Proxy import tech.antibytes.kmock.KMockContract.Reference import tech.antibytes.kmock.util.format @@ -20,7 +22,7 @@ import tech.antibytes.kmock.util.format internal class VerificationChain( private val references: List, private val assertions: Assertions = Assertions, -) : AssertionChain, KMockContract.Assert { +) : AssertionChain, ChainedAssertion { private val invocation = atomic(0) private fun getProxyIdSet(): Set { @@ -65,19 +67,19 @@ internal class VerificationChain( invocation.update { actual + 1 } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalled() { + override fun FunProxy<*, *>.hasBeenCalled() { runAssertion(this) { callIndex -> assertions.hasBeenCalledAtIndex(this, callIndex) } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWithVoid() { + override fun FunProxy<*, *>.hasBeenCalledWithVoid() { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithVoidAtIndex(this, callIndex) } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWith(vararg arguments: Any?) { + override fun FunProxy<*, *>.hasBeenCalledWith(vararg arguments: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithAtIndex( proxy = this, @@ -87,7 +89,7 @@ internal class VerificationChain( } } - override fun KMockContract.FunProxy<*, *>.hasBeenStrictlyCalledWith(vararg arguments: Any?) { + override fun FunProxy<*, *>.hasBeenStrictlyCalledWith(vararg arguments: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenStrictlyCalledWithAtIndex( proxy = this, @@ -97,7 +99,7 @@ internal class VerificationChain( } } - override fun KMockContract.FunProxy<*, *>.hasBeenCalledWithout(vararg illegal: Any?) { + override fun FunProxy<*, *>.hasBeenCalledWithout(vararg illegal: Any?) { runAssertion(this) { callIndex -> assertions.hasBeenCalledWithoutAtIndex( proxy = this, @@ -107,19 +109,19 @@ internal class VerificationChain( } } - override fun KMockContract.PropertyProxy<*>.wasGotten() { + override fun PropertyProxy<*>.wasGotten() { runAssertion(this) { callIndex -> assertions.wasGottenAtIndex(proxy = this, callIndex = callIndex) } } - override fun KMockContract.PropertyProxy<*>.wasSet() { + override fun PropertyProxy<*>.wasSet() { runAssertion(this) { callIndex -> assertions.wasSetAtIndex(proxy = this, callIndex = callIndex) } } - override fun KMockContract.PropertyProxy<*>.wasSetTo(value: Any?) { + override fun PropertyProxy<*>.wasSetTo(value: Any?) { runAssertion(this) { callIndex -> assertions.wasSetToAtIndex( proxy = this, diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt index 1595ca6b..34ba0137 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt @@ -32,8 +32,8 @@ class AssertionChainSpec { @Test @JsName("fn1") - fun `It fulfils Assert`() { - AssertionChain(emptyList()) fulfils KMockContract.Assert::class + fun `It fulfils ChainedAssertion`() { + AssertionChain(emptyList()) fulfils KMockContract.ChainedAssertion::class } private fun invoke( diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt index 86b67956..451e9c02 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt @@ -34,8 +34,8 @@ class VerificationChainSpec { @Test @JsName("fn1") - fun `It fulfils Assert`() { - VerificationChain(emptyList()) fulfils KMockContract.Assert::class + fun `It fulfils ChainedAssertion`() { + AssertionChain(emptyList()) fulfils KMockContract.ChainedAssertion::class } @Test