diff --git a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt index 926dc82f..fceee946 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/KMockContract.kt @@ -1258,7 +1258,7 @@ object KMockContract { /** * */ - interface Assert : AssertionInsurance, AssertionContext + internal interface Assert : AssertionInsurance, AssertionContext /** * AssertionChain in order to verify over multiple Handles. @@ -1266,14 +1266,6 @@ object KMockContract { * @author Matthias Geisler */ interface AssertionChain { - /** - * Propagates the expected invocation to the Chain and asserts it against the actual values. - * @param expected the expected Invocation. - * @throws AssertionError if the expected value does not match the actual value. - */ - @Throws(AssertionError::class) - fun propagate(expected: Expectation) - /** * 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. 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 ec4d6ce1..5fedf534 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/AssertionChain.kt @@ -6,16 +6,11 @@ package tech.antibytes.kmock.verification -import co.touchlab.stately.collections.IsoMutableMap -import co.touchlab.stately.collections.sharedMutableMapOf import kotlinx.atomicfu.atomic import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Assertions -import tech.antibytes.kmock.KMockContract.Expectation import tech.antibytes.kmock.KMockContract.Proxy import tech.antibytes.kmock.KMockContract.Reference -import tech.antibytes.kmock.KMockContract.STRICT_CALL_IDX_NOT_FOUND -import tech.antibytes.kmock.KMockContract.STRICT_CALL_IDX_NOT_MATCH import tech.antibytes.kmock.KMockContract.CALL_NOT_FOUND import tech.antibytes.kmock.KMockContract.STRICT_CALL_NOT_MATCH import tech.antibytes.kmock.KMockContract.STRICT_MISSING_EXPECTATION @@ -28,7 +23,6 @@ internal class AssertionChain( private val assertions: Assertions = Assertions ) : AssertionChain, Assert { private val invocation = atomic(0) - private val invokedProxies: IsoMutableMap = sharedMutableMapOf() private fun getProxyIdSet(): Set { val set: MutableSet = mutableSetOf() @@ -48,65 +42,6 @@ internal class AssertionChain( } } - private fun assertProxy( - actual: Reference?, - expected: Expectation - ) { - when { - actual == null -> throw AssertionError( - CALL_NOT_FOUND.format(expected.proxy.id) - ) - actual.proxy !== expected.proxy -> throw AssertionError( - STRICT_CALL_NOT_MATCH.format(expected.proxy.id, actual.proxy.id) - ) - } - } - - private fun assertInvocation( - actual: Reference, - expected: Expectation - ) { - val expectedCallIdxReference = invokedProxies[actual.proxy.id] ?: 0 - val expectedCallIdx = expected.callIndices.firstOrNull { call -> call == expectedCallIdxReference } - - invokedProxies[actual.proxy.id] = expectedCallIdxReference + 1 - - when { - expectedCallIdx == null -> { - throw AssertionError( - STRICT_CALL_IDX_NOT_FOUND.format(expectedCallIdxReference + 1, expected.proxy.id) - ) - } - expectedCallIdx != actual.callIndex -> throw AssertionError( - STRICT_CALL_IDX_NOT_MATCH.format( - expectedCallIdxReference + 1, - expected.proxy.id, - actual.callIndex + 1 - ) - ) - } - } - - @Throws(AssertionError::class) - override fun propagate(expected: Expectation) { - val actual = references.getOrNull(invocation.value) - - try { - assertProxy( - actual = actual, - expected = expected - ) - assertInvocation( - actual = actual!!, - expected = expected - ) - } catch (e: AssertionError) { - throw e - } finally { - invocation.incrementAndGet() - } - } - private fun guardProxy( expected: Proxy<*, *> ) { 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 4bacfe95..51de368a 100644 --- a/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt +++ b/kmock/src/commonMain/kotlin/tech/antibytes/kmock/verification/VerificationChain.kt @@ -6,13 +6,10 @@ package tech.antibytes.kmock.verification -import co.touchlab.stately.collections.IsoMutableMap -import co.touchlab.stately.collections.sharedMutableMapOf import kotlinx.atomicfu.atomic import kotlinx.atomicfu.update import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.KMockContract.Assertions -import tech.antibytes.kmock.KMockContract.Expectation import tech.antibytes.kmock.KMockContract.NOT_PART_OF_CHAIN import tech.antibytes.kmock.KMockContract.Proxy import tech.antibytes.kmock.KMockContract.Reference @@ -25,7 +22,6 @@ internal class VerificationChain( private val assertions: Assertions = Assertions, ) : AssertionChain, KMockContract.Assert { private val invocation = atomic(0) - private val invokedProxies: IsoMutableMap = sharedMutableMapOf() private fun getProxyIdSet(): Set { val set: MutableSet = mutableSetOf() @@ -45,74 +41,6 @@ internal class VerificationChain( } } - private fun assertProxy( - expected: Expectation, - actual: Int? - ) { - if (actual == null) { - throw AssertionError( - KMockContract.NON_STRICT_CALL_NOT_FOUND.format(expected.proxy.id) - ) - } - } - - private fun assertInvocation( - expected: Expectation, - expectedCallIdx: Int?, - ) { - if (expectedCallIdx == null) { - throw AssertionError(CALL_NOT_FOUND.format(expected.proxy.id)) - } - } - - private fun findInvocation( - expected: Expectation, - actual: Reference, - ): Int? { - val expectedCallIdxReference = invokedProxies[actual.proxy.id] ?: 0 - val expectedCallIdx = expected.callIndices.firstOrNull { call -> call >= expectedCallIdxReference } - - invokedProxies[actual.proxy.id] = expectedCallIdxReference + 1 - - return expectedCallIdx - } - - @Throws(AssertionError::class) - override fun propagate(expected: Expectation) { - while (invocation.value <= references.size) { - val actualReferenceIdx = findProxy(expected.proxy) - - try { - assertProxy( - actual = actualReferenceIdx, - expected = expected, - ) - } catch (e: AssertionError) { - throw e - } - - val actualInvocation = findInvocation( - expected = expected, - actual = references[actualReferenceIdx!!] - ) - - try { - assertInvocation( - expected = expected, - expectedCallIdx = actualInvocation, - ) - } catch (e: AssertionError) { - throw e - } finally { - invocation.update { actualReferenceIdx + 1 } - } - - if (actualInvocation == references[actualReferenceIdx].callIndex) { - break - } - } - } - private fun findProxy(expected: Proxy<*, *>): Int? { for (idx in invocation.value until references.size) { if (references[idx].proxy === expected) { 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 b7638014..572fe3f5 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/AssertionChainSpec.kt @@ -37,166 +37,13 @@ class AssertionChainSpec { AssertionChain(emptyList()) fulfils KMockContract.Assert::class } - @Test - @JsName("fn2") - fun `Given propagate is called and the references are exceeded it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle() - - val chain = AssertionChain(emptyList()) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected ${handle.proxy.id} to be invoked, but no further calls were captured." - } - - @Test - @JsName("fn3") - fun `Given propagate is called and actual refers not to the same Proxy it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle() - val references = listOf( - Reference(fixture.funProxyFixture(), fixture.fixture()) - ) - - val chain = AssertionChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected ${handle.proxy.id} to be invoked, but ${references[0].proxy.id} was called." - } - - @Test - @JsName("fn4") - fun `Given propagate is called and actual refers to the same Proxy as expected but the invocations are exceeded it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle(calls = 0) - val references = listOf( - Reference(handle.proxy, fixture.fixture()) - ) - - val chain = AssertionChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected 1th call of ${handle.proxy.id} was not made." - } - - @Test - @JsName("fn5") - fun `Given propagate is called and actual refers to the same Proxy as expected but the invocation do not match it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle(calls = 1) - val references = listOf( - Reference(handle.proxy, fixture.fixture()) - ) - - val chain = AssertionChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected 1th call of ${handle.proxy.id} was not made." - } - - @Test - @JsName("fn6") - fun `Given propagate is called and actual refers to the same Proxy as expected but the invocation do not match while working on several handels it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val references = listOf( - Reference(handle.proxy, 0), - Reference(handle.proxy, 2) - ) - - val chain = AssertionChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - chain.propagate(handle) - } - - error.message mustBe "Expected 2th call of ${handle.proxy.id}, but it refers to the ${references[1].callIndex + 1}th call." - } - - @Test - @JsName("fn7") - fun `Given propagate is called and actual refers to the same Proxy as expected but the invocation do not match while working on several handels and references it fails`() { - // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), - Reference(handle1.proxy, 1), - Reference(handle2.proxy, 2), - ) - - val chain = AssertionChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - chain.propagate(handle2) - } - - error.message mustBe "Expected 2th call of ${handle2.proxy.id}, but it refers to the ${references[3].callIndex + 1}th call." - } - - @Test - @JsName("fn8") - fun `Given propagate is called and actual refers to the same Proxy as expected and the invocation match it accepts`() { - // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), - Reference(handle1.proxy, 1), - Reference(handle2.proxy, 1), - ) - - val chain = AssertionChain(references) - - // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - chain.propagate(handle2) - } + private fun invoke( + chain: AssertionChain, + action: AssertionChain.() -> Unit + ) = action(chain) @Test - @JsName("fn9") + @JsName("fn2") fun `Given ensureAllReferencesAreEvaluated is called it fails if not all References had been evaluated`() { // Given val references = listOf( @@ -216,30 +63,33 @@ class AssertionChainSpec { } @Test - @JsName("fn10") + @JsName("fn3") fun `Given ensureAllReferencesAreEvaluated is called it accepts if all References had been evaluated`() { // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(0) - ) + val proxy1 = fixture.funProxyFixture() + val proxy2 = fixture.funProxyFixture() val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), + Reference(proxy1, 0), + Reference(proxy2, 0), ) - val chain = AssertionChain(references) + val assertions = AssertionsStub( + hasBeenCalledAtIndex = { _, _ -> Unit } + ) + + val chain = AssertionChain(references, assertions) // When - chain.propagate(handle1) - chain.propagate(handle2) + invoke(chain) { + proxy1.hasBeenCalled() + proxy2.hasBeenCalled() + } + chain.ensureAllReferencesAreEvaluated() } @Test - @JsName("fn11") + @JsName("fn4") fun `Given ensureVerification it fails if the given mock is not part of it`() { // Given val proxy = fixture.funProxyFixture() @@ -256,7 +106,7 @@ class AssertionChainSpec { } @Test - @JsName("fn12") + @JsName("fn5") fun `Given ensureVerification it accepts if the given Proxy is part of it`() { // Given val proxy = fixture.funProxyFixture() @@ -270,13 +120,8 @@ class AssertionChainSpec { container.ensureVerificationOf(proxy) } - private fun invoke( - chain: AssertionChain, - action: AssertionChain.() -> Unit - ) = action(chain) - @Test - @JsName("fn13") + @JsName("fn6") fun `Given hasBeenCalled is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -295,7 +140,7 @@ class AssertionChainSpec { } @Test - @JsName("fn14") + @JsName("fn7") fun `Given hasBeenCalled is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -320,7 +165,7 @@ class AssertionChainSpec { } @Test - @JsName("fn15") + @JsName("fn8") fun `Given hasBeenCalled is called in a Chain it delegates the call to the given Assertions`() { // Given val expectedProxy = fixture.funProxyFixture() @@ -351,7 +196,7 @@ class AssertionChainSpec { } @Test - @JsName("fn16") + @JsName("fn9") fun `Given hasBeenCalledWithVoid is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -370,7 +215,7 @@ class AssertionChainSpec { } @Test - @JsName("fn17") + @JsName("fn10") fun `Given hasBeenCalledWithVoid is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -395,7 +240,7 @@ class AssertionChainSpec { } @Test - @JsName("fn18") + @JsName("fn11") fun `Given hasBeenCalledWithVoid is called in a Chain it the delegates the call to the Assertions`() { // Given val expectedProxy = fixture.funProxyFixture() @@ -426,7 +271,7 @@ class AssertionChainSpec { } @Test - @JsName("fn19") + @JsName("fn12") fun `Given hasBeenCalledWith is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -445,7 +290,7 @@ class AssertionChainSpec { } @Test - @JsName("fn20") + @JsName("fn13") fun `Given hasBeenCalledWith is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -470,7 +315,7 @@ class AssertionChainSpec { } @Test - @JsName("fn21") + @JsName("fn14") fun `Given hasBeenCalledWith is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -508,7 +353,7 @@ class AssertionChainSpec { } @Test - @JsName("fn22") + @JsName("fn15") fun `Given hasBeenStrictlyCalledWith is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -527,7 +372,7 @@ class AssertionChainSpec { } @Test - @JsName("fn23") + @JsName("fn16") fun `Given hasBeenStrictlyCalledWith is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -552,7 +397,7 @@ class AssertionChainSpec { } @Test - @JsName("fn24") + @JsName("fn17") fun `Given hasBeenStrictlyCalledWith is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -590,7 +435,7 @@ class AssertionChainSpec { } @Test - @JsName("fn25") + @JsName("fn18") fun `Given hasBeenCalledWithout is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -609,7 +454,7 @@ class AssertionChainSpec { } @Test - @JsName("fn26") + @JsName("fn18") fun `Given hasBeenCalledWithout is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -634,7 +479,7 @@ class AssertionChainSpec { } @Test - @JsName("fn27") + @JsName("fn19") fun `Given hasBeenCalledWithout is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -672,7 +517,7 @@ class AssertionChainSpec { } @Test - @JsName("fn28") + @JsName("fn20") fun `Given wasGotten is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -691,7 +536,7 @@ class AssertionChainSpec { } @Test - @JsName("fn29") + @JsName("fn21") fun `Given wasGotten is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -716,7 +561,7 @@ class AssertionChainSpec { } @Test - @JsName("fn30") + @JsName("fn22") fun `Given wasGotten is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -749,7 +594,7 @@ class AssertionChainSpec { } @Test - @JsName("fn31") + @JsName("fn23") fun `Given wasSet is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -768,7 +613,7 @@ class AssertionChainSpec { } @Test - @JsName("fn32") + @JsName("fn24") fun `Given wasSet is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -793,7 +638,7 @@ class AssertionChainSpec { } @Test - @JsName("fn33") + @JsName("fn25") fun `Given wasSet is called in a Chain it it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -826,7 +671,7 @@ class AssertionChainSpec { } @Test - @JsName("fn34") + @JsName("fn26") fun `Given wasSetTo is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -845,7 +690,7 @@ class AssertionChainSpec { } @Test - @JsName("fn35") + @JsName("fn27") fun `Given wasSetTo is called in a Chain it fails if the current Reference and the expected Proxies are not the same`() { // Given val id1: String = fixture.fixture() @@ -870,7 +715,7 @@ class AssertionChainSpec { } @Test - @JsName("fn36") + @JsName("fn28") fun `Given wasSetTo is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -906,4 +751,80 @@ class AssertionChainSpec { capturedIdx mustBe callIdx capturedValue sameAs expectedValue } + + @Test + @JsName("fn29") + fun `It respects the order of the chain`() { + // Given + val proxy1 = fixture.funProxyFixture() + val proxy2 = fixture.funProxyFixture() + val proxy3 = fixture.propertyProxyFixture() + val references = listOf( + Reference(proxy1, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy2, fixture.fixture()), + Reference(proxy1, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy2, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy1, fixture.fixture()), + ) + + val capturedProxies: MutableList> = mutableListOf() + val capturedCallIdx: MutableList = mutableListOf() + + val assertions = AssertionsStub( + hasBeenCalledAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + + }, + hasBeenCalledWithVoidAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenCalledWithAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenStrictlyCalledWithAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenCalledWithoutAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasGottenAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasSetAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasSetToAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + } + ) + + val chain = AssertionChain(references, assertions) + + // When + invoke(chain) { + proxy1.hasBeenCalled() + proxy3.wasGotten() + proxy2.hasBeenCalledWithVoid() + proxy1.hasBeenCalledWith(fixture.fixture()) + proxy3.wasSet() + proxy2.hasBeenStrictlyCalledWith(fixture.fixture()) + proxy3.wasSetTo(fixture.fixture()) + proxy1.hasBeenCalledWithout(fixture.fixture()) + } + + // Then + capturedProxies mustBe references.map { it.proxy } + capturedCallIdx mustBe references.map { it.callIndex } + } } 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 db7735e1..da8f2fa0 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/kmock/verification/VerificationChainSpec.kt @@ -15,6 +15,7 @@ import tech.antibytes.kmock.fixture.propertyProxyFixture import tech.antibytes.mock.AssertionsStub import tech.antibytes.util.test.fixture.fixture import tech.antibytes.util.test.fixture.kotlinFixture +import tech.antibytes.util.test.fixture.listFixture import tech.antibytes.util.test.fulfils import tech.antibytes.util.test.mustBe import tech.antibytes.util.test.sameAs @@ -39,150 +40,6 @@ class VerificationChainSpec { @Test @JsName("fn2") - fun `Given propagate is called and the references are exceeded it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle() - - val chain = VerificationChain(emptyList()) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected ${handle.proxy.id} to be invoked, but no call was captured with the given arguments." - } - - @Test - @JsName("fn3") - fun `Given propagate is called and actual refers same Proxy as expected but the invocations are exceeded it fails`() { - // Given - val handle = fixture.fixtureVerificationHandle(calls = 0) - val references = listOf( - Reference(handle.proxy, fixture.fixture()) - ) - - val chain = VerificationChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected ${handle.proxy.id} to be invoked, but no further calls were captured." - } - - @Test - @JsName("fn4") - fun `Given propagate is called and actual refers same Proxy as expected but the invocations are exceeded over multible Handlesit fails`() { - // Given - val handle = fixture.fixtureVerificationHandle( - callIndices = listOf(3) - ) - val references = listOf( - Reference(handle.proxy, 0), - Reference(handle.proxy, 1), - Reference(handle.proxy, 2), - ) - - val chain = VerificationChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle) - } - - error.message mustBe "Expected ${handle.proxy.id} to be invoked, but no call was captured with the given arguments." - } - - @Test - @JsName("fn5") - fun `Given propagate is called and actual refers to the same Proxy as expected but the invocation do not match while working on several handels and referencesit fails`() { - // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), - Reference(handle1.proxy, 1), - Reference(handle2.proxy, 2), - ) - - val chain = VerificationChain(references) - - // Then - val error = assertFailsWith { - // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - chain.propagate(handle2) - } - - error.message mustBe "Expected ${handle2.proxy.id} to be invoked, but no call was captured with the given arguments." - } - - @Test - @JsName("fn6") - fun `Given propagate is called and actual refers to the same Proxy as expected and the invocation match it accepts`() { - // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 1) - ) - val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), - Reference(handle1.proxy, 1), - Reference(handle2.proxy, 1), - ) - - val chain = VerificationChain(references) - - // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - chain.propagate(handle2) - } - - @Test - @JsName("fn7") - fun `Given propagate is called and actual refers to the same Proxy as expected and the invocation match it accepts for incomplete calls`() { - // Given - val handle1 = fixture.fixtureVerificationHandle( - callIndices = listOf(0, 2) - ) - val handle2 = fixture.fixtureVerificationHandle( - callIndices = listOf(1) - ) - val references = listOf( - Reference(handle1.proxy, 0), - Reference(handle2.proxy, 0), - Reference(handle1.proxy, 1), - Reference(handle2.proxy, 1), - Reference(handle1.proxy, 2), - ) - - val chain = VerificationChain(references) - - // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - } - - @Test - @JsName("fn8") fun `Given ensureAllReferencesAreEvaluated is calledit accepts allways`() { // Given val handle1 = fixture.fixtureVerificationHandle( @@ -201,15 +58,11 @@ class VerificationChainSpec { val chain = VerificationChain(references) // When - chain.propagate(handle1) - chain.propagate(handle2) - chain.propagate(handle1) - chain.ensureAllReferencesAreEvaluated() } @Test - @JsName("fn9") + @JsName("fn3") fun `Given ensureVerification it fails if the given Proxy is not part of it`() { // Given val proxy = fixture.funProxyFixture() @@ -226,7 +79,7 @@ class VerificationChainSpec { } @Test - @JsName("fn10") + @JsName("fn4") fun `Given ensureVerification it accepts if the given Proxy is part of it`() { // Given val proxy = fixture.funProxyFixture() @@ -246,7 +99,7 @@ class VerificationChainSpec { ) = action(chain) @Test - @JsName("fn12") + @JsName("fn5") fun `Given hasBeenCalled is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -265,7 +118,7 @@ class VerificationChainSpec { } @Test - @JsName("fn13") + @JsName("fn6") fun `Given hasBeenCalled is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -290,7 +143,7 @@ class VerificationChainSpec { } @Test - @JsName("fn14") + @JsName("fn7") fun `Given hasBeenCalled is called in a Chain it delegates the call to the given Assertions`() { // Given val expectedProxy = fixture.funProxyFixture() @@ -321,7 +174,7 @@ class VerificationChainSpec { } @Test - @JsName("fn15") + @JsName("fn8") fun `Given hasBeenCalledWithVoid is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -340,7 +193,7 @@ class VerificationChainSpec { } @Test - @JsName("fn16") + @JsName("fn9") fun `Given hasBeenCalledWithVoid is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -365,7 +218,7 @@ class VerificationChainSpec { } @Test - @JsName("fn17") + @JsName("fn10") fun `Given hasBeenCalledWithVoid is called in a Chain it the delegates the call to the Assertions`() { // Given val expectedProxy = fixture.funProxyFixture() @@ -396,7 +249,7 @@ class VerificationChainSpec { } @Test - @JsName("fn18") + @JsName("fn11") fun `Given hasBeenCalledWith is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -415,7 +268,7 @@ class VerificationChainSpec { } @Test - @JsName("fn19") + @JsName("fn12") fun `Given hasBeenCalledWith is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -440,7 +293,7 @@ class VerificationChainSpec { } @Test - @JsName("fn20") + @JsName("fn13") fun `Given hasBeenCalledWith is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -478,7 +331,7 @@ class VerificationChainSpec { } @Test - @JsName("fn21") + @JsName("fn14") fun `Given hasBeenStrictlyCalledWith is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -497,7 +350,7 @@ class VerificationChainSpec { } @Test - @JsName("fn22") + @JsName("fn15") fun `Given hasBeenStrictlyCalledWith is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -522,7 +375,7 @@ class VerificationChainSpec { } @Test - @JsName("fn23") + @JsName("fn16") fun `Given hasBeenStrictlyCalledWith is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -560,7 +413,7 @@ class VerificationChainSpec { } @Test - @JsName("fn24") + @JsName("fn17") fun `Given hasBeenCalledWithout is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -579,7 +432,7 @@ class VerificationChainSpec { } @Test - @JsName("fn25") + @JsName("fn18") fun `Given hasBeenCalledWithout is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -604,7 +457,7 @@ class VerificationChainSpec { } @Test - @JsName("fn26") + @JsName("fn19") fun `Given hasBeenCalledWithout is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -642,7 +495,7 @@ class VerificationChainSpec { } @Test - @JsName("fn27") + @JsName("fn20") fun `Given wasGotten is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -661,7 +514,7 @@ class VerificationChainSpec { } @Test - @JsName("fn28") + @JsName("fn21") fun `Given wasGotten is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -686,7 +539,7 @@ class VerificationChainSpec { } @Test - @JsName("fn29") + @JsName("fn22") fun `Given wasGotten is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -719,7 +572,7 @@ class VerificationChainSpec { } @Test - @JsName("fn30") + @JsName("fn23") fun `Given wasSet is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -738,7 +591,7 @@ class VerificationChainSpec { } @Test - @JsName("fn31") + @JsName("fn24") fun `Given wasSet is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -763,7 +616,7 @@ class VerificationChainSpec { } @Test - @JsName("fn32") + @JsName("fn25") fun `Given wasSet is called in a Chain it it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -796,7 +649,7 @@ class VerificationChainSpec { } @Test - @JsName("fn33") + @JsName("fn26") fun `Given wasSetTo is called in a Chain it fails if the current References are exhausted`() { // Given val id: String = fixture.fixture() @@ -815,7 +668,7 @@ class VerificationChainSpec { } @Test - @JsName("fn34") + @JsName("fn27") fun `Given wasSetTo is called in a Chain it fails if the expected Proxies was not found`() { // Given val id1: String = fixture.fixture() @@ -840,7 +693,7 @@ class VerificationChainSpec { } @Test - @JsName("fn35") + @JsName("fn28") fun `Given wasSetTo is called in a Chain it delegates the call to the assertions`() { // Given val id: String = fixture.fixture() @@ -876,4 +729,111 @@ class VerificationChainSpec { capturedIdx mustBe callIdx capturedValue sameAs expectedValue } + + @Test + @JsName("fn29") + fun `It respects the pratial order of the chain`() { + // Given + val proxy1 = fixture.funProxyFixture() + val proxy2 = fixture.funProxyFixture() + val proxy3 = fixture.propertyProxyFixture() + + val expectedProxies = listOf( + proxy1, + proxy3, + proxy2, + proxy1, + proxy3, + proxy2, + proxy3, + proxy1, + ) + + val expectedCallIndices: List = fixture.listFixture(size = 8) + + val references = listOf( + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy1, expectedCallIndices[0]), + Reference(proxy3, expectedCallIndices[1]), + Reference(proxy2, expectedCallIndices[2]), + Reference(proxy2, fixture.fixture()), + Reference(proxy2, fixture.fixture()), + Reference(proxy1, expectedCallIndices[3]), + Reference(proxy1, fixture.fixture()), + Reference(proxy1, fixture.fixture()), + Reference(proxy1, fixture.fixture()), + Reference(proxy3, expectedCallIndices[4]), + Reference(proxy2, expectedCallIndices[5]), + Reference(proxy3, expectedCallIndices[6]), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy3, fixture.fixture()), + Reference(proxy1, expectedCallIndices[7]), + ) + + + + val capturedProxies: MutableList> = mutableListOf() + val capturedCallIdx: MutableList = mutableListOf() + + val assertions = AssertionsStub( + hasBeenCalledAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + + }, + hasBeenCalledWithVoidAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenCalledWithAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenStrictlyCalledWithAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + hasBeenCalledWithoutAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasGottenAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasSetAtIndex = { givenProxy, givenIdx -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + }, + wasSetToAtIndex = { givenProxy, givenIdx, _ -> + capturedProxies.add(givenProxy) + capturedCallIdx.add(givenIdx) + } + ) + + val chain = VerificationChain(references, assertions) + + // When + invoke(chain) { + proxy1.hasBeenCalled() + proxy3.wasGotten() + proxy2.hasBeenCalledWithVoid() + proxy1.hasBeenCalledWith(fixture.fixture()) + proxy3.wasSet() + proxy2.hasBeenStrictlyCalledWith(fixture.fixture()) + proxy3.wasSetTo(fixture.fixture()) + proxy1.hasBeenCalledWithout(fixture.fixture()) + } + + // Then + capturedProxies mustBe expectedProxies + capturedCallIdx mustBe expectedCallIndices + } } diff --git a/kmock/src/commonTest/kotlin/tech/antibytes/mock/AssertionChainStub.kt b/kmock/src/commonTest/kotlin/tech/antibytes/mock/AssertionChainStub.kt index 7a12e528..b22161e5 100644 --- a/kmock/src/commonTest/kotlin/tech/antibytes/mock/AssertionChainStub.kt +++ b/kmock/src/commonTest/kotlin/tech/antibytes/mock/AssertionChainStub.kt @@ -9,14 +9,7 @@ package tech.antibytes.mock import tech.antibytes.kmock.KMockContract import tech.antibytes.kmock.error.MockError -internal class AssertionChainStub( - private val propagate: ((KMockContract.Expectation) -> Unit)? = null -) : KMockContract.AssertionChain { - override fun propagate(expected: KMockContract.Expectation) { - return propagate?.invoke(expected) - ?: throw MockError.MissingStub("Missing SideEffect propagate") - } - +internal class AssertionChainStub : KMockContract.AssertionChain { override fun ensureAllReferencesAreEvaluated() { TODO("Not yet implemented") }