From cd23d92794f50a030223ecc3f1cda9eb9d758613 Mon Sep 17 00:00:00 2001 From: Mattia Tommasone Date: Tue, 24 Nov 2020 23:06:29 +0100 Subject: [PATCH 1/2] Added a check to prevent slots from being used when verifying multiple calls + cleared some warnings --- .../io/mockk/impl/verify/LCSMatchingAlgo.kt | 10 +-- .../impl/verify/UnorderedCallVerifier.kt | 15 ++++- .../test/kotlin/io/mockk/gh/Issue352Test.kt | 62 +++++++++++++++++++ .../test/kotlin/io/mockk/gh/Issue353Test.kt | 4 +- .../kotlin/io/mockk/impl/InternalPlatform.kt | 2 +- .../test/kotlin/io/mockk/gh/Issue386Test.kt | 6 +- 6 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 mockk/common/src/test/kotlin/io/mockk/gh/Issue352Test.kt diff --git a/mockk/common/src/main/kotlin/io/mockk/impl/verify/LCSMatchingAlgo.kt b/mockk/common/src/main/kotlin/io/mockk/impl/verify/LCSMatchingAlgo.kt index 8f3b230fc..bc22c8bda 100644 --- a/mockk/common/src/main/kotlin/io/mockk/impl/verify/LCSMatchingAlgo.kt +++ b/mockk/common/src/main/kotlin/io/mockk/impl/verify/LCSMatchingAlgo.kt @@ -5,8 +5,8 @@ import io.mockk.RecordedCall class LCSMatchingAlgo( val allCalls: List, - val verificationSequence: List, - val captureBlocks: MutableList<() -> Unit>? = null + private val verificationSequence: List, + private val captureBlocks: MutableList<() -> Unit>? = null ) { private val nEdits = Array(allCalls.size) { Array(verificationSequence.size) { 0 } } private val path = Array(allCalls.size) { Array(verificationSequence.size) { '?' } } @@ -72,8 +72,4 @@ class LCSMatchingAlgo( } } } - - fun postProcess() { - backTrackCalls(allCalls.size - 1, verificationSequence.size - 1) - } -} \ No newline at end of file +} diff --git a/mockk/common/src/main/kotlin/io/mockk/impl/verify/UnorderedCallVerifier.kt b/mockk/common/src/main/kotlin/io/mockk/impl/verify/UnorderedCallVerifier.kt index bee7d8e8a..bdf572e76 100644 --- a/mockk/common/src/main/kotlin/io/mockk/impl/verify/UnorderedCallVerifier.kt +++ b/mockk/common/src/main/kotlin/io/mockk/impl/verify/UnorderedCallVerifier.kt @@ -1,9 +1,13 @@ package io.mockk.impl.verify +import io.mockk.CapturingSlotMatcher import io.mockk.InternalPlatformDsl.toStr import io.mockk.Invocation import io.mockk.InvocationMatcher -import io.mockk.MockKGateway.* +import io.mockk.MockKException +import io.mockk.MockKGateway.CallVerifier +import io.mockk.MockKGateway.VerificationParameters +import io.mockk.MockKGateway.VerificationResult import io.mockk.MockKSettings import io.mockk.RecordedCall import io.mockk.impl.InternalPlatform @@ -51,6 +55,13 @@ open class UnorderedCallVerifier( val allCallsForMock = stub.allRecordedCalls() val allCallsForMockMethod = stub.allRecordedCalls(matcher.method) + if(allCallsForMockMethod.size > 1 && matcher.args.any { it is CapturingSlotMatcher<*> }) { + val msg = "$matcher execution is being verified more than once and its arguments are being captured with a slot.\n" + + "This will store only the argument of the last invocation in the slot.\n" + + "If you want to store all the arguments, use a mutableList to capture arguments." + throw MockKException(msg) + } + val result = if (min == 0 && max == 0) { if (!allCallsForMockMethod.any(matcher::match)) { VerificationResult.OK(listOf()) @@ -171,4 +182,4 @@ open class UnorderedCallVerifier( } return str.toString() } -} \ No newline at end of file +} diff --git a/mockk/common/src/test/kotlin/io/mockk/gh/Issue352Test.kt b/mockk/common/src/test/kotlin/io/mockk/gh/Issue352Test.kt new file mode 100644 index 000000000..307ffac54 --- /dev/null +++ b/mockk/common/src/test/kotlin/io/mockk/gh/Issue352Test.kt @@ -0,0 +1,62 @@ +package io.mockk.gh + +import io.mockk.MockKException +import io.mockk.every +import io.mockk.mockk +import io.mockk.slot +import io.mockk.verify +import io.mockk.verifyOrder +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class Issue352Test { + + open class MockedSubject { + open fun doSomething(id: String?, data: Any?): String { + throw IllegalStateException("Not mocked :(") + } + } + + private val mock = mockk() + + @BeforeTest + fun setup() { + every { mock.doSomething("1", "data1") } returns "result1" + every { mock.doSomething("2", "data2") } returns "result2" + } + + @Test + fun `It throws a MockkException when verifying the same function twice with slots`() { + mock.doSomething("1", "data1") + mock.doSomething("2", "data2") + + val dataSlotId1 = slot() + val dataSlotId2 = slot() + + assertFailsWith { + verify { + mock.doSomething("1", capture(dataSlotId1)) + mock.doSomething("2", capture(dataSlotId2)) + } + } + } + + @Test + fun `It allows multiple capturings of the same function using a mutableList`() { + mock.doSomething("1", "data1") + mock.doSomething("2", "data2") + + val slotList = mutableListOf() + + verify { + mock.doSomething("1", capture(slotList)) + mock.doSomething("2", capture(slotList)) + } + + assertEquals("data1", slotList[0]) + assertEquals("data2", slotList[1]) + } + +} diff --git a/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt b/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt index e8ae0316c..afb2aeee5 100644 --- a/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt +++ b/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt @@ -12,7 +12,7 @@ class Issue353Test { @Test fun testNullableCapture() { class Mock { - fun call(arg: String?) { + fun call(_: String?) { } } @@ -28,4 +28,4 @@ class Issue353Test { assertEquals(args, list) } -} \ No newline at end of file +} diff --git a/mockk/jvm/src/main/kotlin/io/mockk/impl/InternalPlatform.kt b/mockk/jvm/src/main/kotlin/io/mockk/impl/InternalPlatform.kt index 080711715..785363a0d 100644 --- a/mockk/jvm/src/main/kotlin/io/mockk/impl/InternalPlatform.kt +++ b/mockk/jvm/src/main/kotlin/io/mockk/impl/InternalPlatform.kt @@ -147,7 +147,7 @@ actual object InternalPlatform { inline fun loadPlugin(className: String, msg: String = "") = try { - T::class.cast(Class.forName(className).newInstance()) + T::class.cast(Class.forName(className).getDeclaredConstructor().newInstance()) } catch (ex: Exception) { throw MockKException("Failed to load plugin. $className $msg", ex) } diff --git a/mockk/jvm/src/test/kotlin/io/mockk/gh/Issue386Test.kt b/mockk/jvm/src/test/kotlin/io/mockk/gh/Issue386Test.kt index b96a4764c..b5e7e26c0 100644 --- a/mockk/jvm/src/test/kotlin/io/mockk/gh/Issue386Test.kt +++ b/mockk/jvm/src/test/kotlin/io/mockk/gh/Issue386Test.kt @@ -2,10 +2,10 @@ package io.mockk.gh import io.mockk.MockKAnnotations import io.mockk.impl.annotations.RelaxedMockK -import junit.framework.Assert.assertEquals -import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue class ReturningCollections { fun getList(): List { @@ -80,4 +80,4 @@ class Issue386Test { assertTrue(hashset.isEmpty()) } -} \ No newline at end of file +} From 930a079b5cfc0a8b7459e77f6c240d8dff710ba7 Mon Sep 17 00:00:00 2001 From: Mattia Tommasone Date: Wed, 25 Nov 2020 09:18:59 +0100 Subject: [PATCH 2/2] Fixing a warning accidentally triggered an error, implemented a better fix --- mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt b/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt index afb2aeee5..872e4cd66 100644 --- a/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt +++ b/mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt @@ -12,7 +12,8 @@ class Issue353Test { @Test fun testNullableCapture() { class Mock { - fun call(_: String?) { + fun call(unused: String?) { + println(unused) } }