Skip to content

Commit

Permalink
Merge pull request #533 from mockk/fix-issue-352
Browse files Browse the repository at this point in the history
Added a check to prevent slots from being used when verifying multiple calls
  • Loading branch information
Raibaz committed Nov 29, 2020
2 parents 8542a86 + 930a079 commit 06c5e73
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 15 deletions.
Expand Up @@ -5,8 +5,8 @@ import io.mockk.RecordedCall

class LCSMatchingAlgo(
val allCalls: List<Invocation>,
val verificationSequence: List<RecordedCall>,
val captureBlocks: MutableList<() -> Unit>? = null
private val verificationSequence: List<RecordedCall>,
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) { '?' } }
Expand Down Expand Up @@ -72,8 +72,4 @@ class LCSMatchingAlgo(
}
}
}

fun postProcess() {
backTrackCalls(allCalls.size - 1, verificationSequence.size - 1)
}
}
}
@@ -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
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -171,4 +182,4 @@ open class UnorderedCallVerifier(
}
return str.toString()
}
}
}
62 changes: 62 additions & 0 deletions 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<MockedSubject>()

@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<String>()
val dataSlotId2 = slot<String>()

assertFailsWith<MockKException> {
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<String>()

verify {
mock.doSomething("1", capture(slotList))
mock.doSomething("2", capture(slotList))
}

assertEquals("data1", slotList[0])
assertEquals("data2", slotList[1])
}

}
5 changes: 3 additions & 2 deletions mockk/common/src/test/kotlin/io/mockk/gh/Issue353Test.kt
Expand Up @@ -12,7 +12,8 @@ class Issue353Test {
@Test
fun testNullableCapture() {
class Mock {
fun call(arg: String?) {
fun call(unused: String?) {
println(unused)
}
}

Expand All @@ -28,4 +29,4 @@ class Issue353Test {

assertEquals(args, list)
}
}
}
Expand Up @@ -147,7 +147,7 @@ actual object InternalPlatform {

inline fun <reified T : Any> 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)
}
Expand Down
6 changes: 3 additions & 3 deletions mockk/jvm/src/test/kotlin/io/mockk/gh/Issue386Test.kt
Expand Up @@ -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<Any> {
Expand Down Expand Up @@ -80,4 +80,4 @@ class Issue386Test {
assertTrue(hashset.isEmpty())
}

}
}

0 comments on commit 06c5e73

Please sign in to comment.