From a322b2686d584553ff7329abd43237c3dd2f5708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Persg=C3=A5rden?= Date: Sat, 14 Nov 2020 17:39:23 +0100 Subject: [PATCH] Issue 315: Allow to combine @SpyK with @InjectMockKs --- .../kotlin/io/mockk/it/AnnotationsTest.kt | 29 ++++++++++ .../impl/annotations/JvmMockInitializer.kt | 53 +++++++++++++------ 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/mockk/common/src/test/kotlin/io/mockk/it/AnnotationsTest.kt b/mockk/common/src/test/kotlin/io/mockk/it/AnnotationsTest.kt index ee0e6c4f8..53c25500e 100644 --- a/mockk/common/src/test/kotlin/io/mockk/it/AnnotationsTest.kt +++ b/mockk/common/src/test/kotlin/io/mockk/it/AnnotationsTest.kt @@ -86,6 +86,14 @@ class AnnotationsTest { val obj = MockCls() } + class InjectionTarget4{ + lateinit var obj: MockCls + fun op(a: Int): Int { + return obj.op(a) + } + + } + class InjectSourceCls { @MockK lateinit var mock: MockCls @@ -112,4 +120,25 @@ class AnnotationsTest { assertSame(source.mock, source.target2.obj) assertSame(source.mock, source.target3.obj) } + + class InjectIntoSpySourceCls { + @MockK + lateinit var mock: MockCls + + @InjectMockKs + @SpyK + lateinit var target4: InjectionTarget4 + } + + @Test + fun injectIntoSpy() { + val callValue = 5 + val source = InjectIntoSpySourceCls() + MockKAnnotations.init(source) + + every { source.mock.op(any()) } returns callValue + assertNotNull(source.target4) + assertEquals(callValue, source.target4.op(0)) + verify { source.target4.op(any()) } + } } \ No newline at end of file diff --git a/mockk/jvm/src/main/kotlin/io/mockk/impl/annotations/JvmMockInitializer.kt b/mockk/jvm/src/main/kotlin/io/mockk/impl/annotations/JvmMockInitializer.kt index 78636f320..1c56174ad 100644 --- a/mockk/jvm/src/main/kotlin/io/mockk/impl/annotations/JvmMockInitializer.kt +++ b/mockk/jvm/src/main/kotlin/io/mockk/impl/annotations/JvmMockInitializer.kt @@ -45,11 +45,14 @@ class JvmMockInitializer(val gateway: MockKGateway) : MockKGateway.MockInitializ relaxed ) assignRelaxedMockK(property, target) - assignSpyK( - property, - target, - overrideRecordPrivateCalls - ) + + if (!isAnnotatedWith(property)) { + assignSpyK( + property, + target, + overrideRecordPrivateCalls + ) + } } for (property in cls.memberProperties) { @@ -62,8 +65,8 @@ class JvmMockInitializer(val gateway: MockKGateway) : MockKGateway.MockInitializ annotation.injectImmutable, annotation.overrideValues ) - - doInjection(property, target, mockInjector) + val instance = doInjection(property, target, mockInjector) + convertSpyKAnnotatedToSpy(property, instance, overrideRecordPrivateCalls) } property.annotated(target) { annotation -> val mockInjector = MockInjector( @@ -99,6 +102,11 @@ class JvmMockInitializer(val gateway: MockKGateway) : MockKGateway.MockInitializ } } + private fun convertSpyKAnnotatedToSpy(property: KProperty1, instance: Any, overrideRecordPrivateCalls: Boolean): Any { + val spyAnnotation = property.findAnnotation() ?: return instance + return createSpyK(property, spyAnnotation, instance, overrideRecordPrivateCalls) + } + private fun assignSpyK( property: KProperty1, target: Any, @@ -106,18 +114,26 @@ class JvmMockInitializer(val gateway: MockKGateway) : MockKGateway.MockInitializ ) { property.annotated(target) { annotation -> val obj = property.get(target) - - gateway.mockFactory.spyk( - null, - obj, - overrideName(annotation.name, property.name), - moreInterfaces(property), - annotation.recordPrivateCalls - || overrideRecordPrivateCalls - ) + createSpyK(property, annotation, obj, overrideRecordPrivateCalls) } } + private fun createSpyK( + property: KProperty1, + spyAnnotation: SpyK, + instance: Any, + overrideRecordPrivateCalls: Boolean + ): Any { + return gateway.mockFactory.spyk( + null, + instance, + overrideName(spyAnnotation.name, property.name), + moreInterfaces(property), + spyAnnotation.recordPrivateCalls + || overrideRecordPrivateCalls + ) + } + private fun assignRelaxedMockK(property: KProperty1, target: Any) { property.annotated(target) { annotation -> val type = property.returnType.classifier as? KClass<*> @@ -205,6 +221,11 @@ class JvmMockInitializer(val gateway: MockKGateway) : MockKGateway.MockInitializ } } + private inline fun isAnnotatedWith(property: KProperty<*>) : Boolean { + val annotation = property.findAnnotation() + return null != annotation + } + companion object { private fun moreInterfaces(property: KProperty1) = property.annotations