diff --git a/mockk/common/src/main/kotlin/io/mockk/impl/recording/states/RecordingState.kt b/mockk/common/src/main/kotlin/io/mockk/impl/recording/states/RecordingState.kt index 5c594cb05..482790615 100644 --- a/mockk/common/src/main/kotlin/io/mockk/impl/recording/states/RecordingState.kt +++ b/mockk/common/src/main/kotlin/io/mockk/impl/recording/states/RecordingState.kt @@ -62,16 +62,16 @@ abstract class RecordingState(recorder: CommonCallRecorder) : CallRecordingState override fun call(invocation: Invocation): Any? { val retType = recorder.childHinter.nextChildType { invocation.method.returnType } var isTemporaryMock = false - - val retValue = - if (invocation.method.isToString()) { - recorder.stubRepo[invocation.self]?.toStr() ?: "" - } else { - recorder.anyValueGenerator().anyValue(retType, invocation.method.returnTypeNullable) { - isTemporaryMock = true - recorder.mockFactory.temporaryMock(retType) - } - } + val temporaryMock: () -> Any = { + isTemporaryMock = true + recorder.mockFactory.temporaryMock(retType) + } + val retValue = when { + invocation.method.isToString() -> recorder.stubRepo[invocation.self]?.toStr() ?: "" + retType in CollectionTypes -> temporaryMock() + else -> recorder.anyValueGenerator() + .anyValue(retType, invocation.method.returnTypeNullable, orInstantiateVia = temporaryMock) + } if (retValue == null) { isTemporaryMock = false @@ -191,4 +191,14 @@ abstract class RecordingState(recorder: CommonCallRecorder) : CallRecordingState private fun builder(): CallRoundBuilder = callRoundBuilder ?: throw MockKException("Call builder is not initialized. Bad state") + private companion object { + private val CollectionTypes = listOf( + List::class, + Map::class, + Set::class, + ArrayList::class, + HashMap::class, + HashSet::class + ) + } } diff --git a/mockk/jvm/src/test/kotlin/io/mockk/it/CollectionChainStubbingTest.kt b/mockk/jvm/src/test/kotlin/io/mockk/it/CollectionChainStubbingTest.kt new file mode 100644 index 000000000..50291d0b0 --- /dev/null +++ b/mockk/jvm/src/test/kotlin/io/mockk/it/CollectionChainStubbingTest.kt @@ -0,0 +1,68 @@ +package io.mockk.it + +import io.mockk.every +import io.mockk.mockk +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +// Regression tests for GitHub issue #565. +class CollectionChainStubbingTest { + + private interface ReturningCollections { + val list: List + val map: Map + val set: Set + val arrayList: ArrayList + val hashMap: Map + val hashSet: HashSet + } + + @Test + fun list() { + val mock = mockk() + every { mock.list[0] } returns 1 + + assertEquals(1, mock.list[0]) + } + + @Test + fun map() { + val mock = mockk() + every { mock.map["foo"] } returns 1 + + assertEquals(1, mock.map["foo"]) + } + + @Test + fun set() { + val mock = mockk() + every { mock.set.contains(1) } returns true + + assertTrue(mock.set.contains(1)) + } + + @Test + fun arrayList() { + val mock = mockk() + every { mock.arrayList[0] } returns 1 + + assertEquals(1, mock.arrayList[0]) + } + + @Test + fun hashMap() { + val mock = mockk() + every { mock.hashMap["foo"] } returns 1 + + assertEquals(1, mock.hashMap["foo"]) + } + + @Test + fun hashSet() { + val mock = mockk() + every { mock.hashSet.contains(0) } returns true + + assertTrue(mock.hashSet.contains(0)) + } +} \ No newline at end of file