Skip to content

Commit

Permalink
Merge pull request #872 from qoomon/master
Browse files Browse the repository at this point in the history
fix: fix value class field determination
  • Loading branch information
Raibaz committed Jul 30, 2022
2 parents 96d3b93 + 197e25a commit 6ce0616
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 11 deletions.
6 changes: 3 additions & 3 deletions agent/android/src/main/kotlin/io/mockk/ValueClassSupport.kt
Expand Up @@ -3,8 +3,8 @@ package io.mockk
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField

// TODO this class is copy-pasted and should be de-duplicated
// see https://github.com/mockk/mockk/issues/857
Expand Down Expand Up @@ -45,10 +45,10 @@ private val <T : Any> KClass<T>.boxedProperty: KProperty1<T, *>
get() = if (!this.isValue_safe) {
throw UnsupportedOperationException("$this is not a value class")
} else {
// value classes always have exactly one property
@Suppress("UNCHECKED_CAST")
valueClassFieldCache.getOrPut(this) {
this.declaredMemberProperties.first().apply { isAccessible = true }
// value classes always have exactly one property with a backing field
this.declaredMemberProperties.first { it.javaField != null }.apply { isAccessible = true }
} as KProperty1<T, *>
}

Expand Down
6 changes: 3 additions & 3 deletions agent/jvm/src/main/kotlin/io/mockk/ValueClassSupport.kt
Expand Up @@ -3,8 +3,8 @@ package io.mockk
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField

// TODO this class is copy-pasted and should be de-duplicated
// see https://github.com/mockk/mockk/issues/857
Expand Down Expand Up @@ -45,10 +45,10 @@ private val <T : Any> KClass<T>.boxedProperty: KProperty1<T, *>
get() = if (!this.isValue_safe) {
throw UnsupportedOperationException("$this is not a value class")
} else {
// value classes always have exactly one property
@Suppress("UNCHECKED_CAST")
valueClassFieldCache.getOrPut(this) {
this.declaredMemberProperties.first().apply { isAccessible = true }
// value classes always have exactly one property with a backing field
this.declaredMemberProperties.first { it.javaField != null }.apply { isAccessible = true }
} as KProperty1<T, *>
}

Expand Down
5 changes: 3 additions & 2 deletions dsl/jvm/src/main/kotlin/io/mockk/ValueClassSupportDsl.kt
Expand Up @@ -4,6 +4,7 @@ import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField

/**
* Provides value class support in the `mockk-dsl-jvm` subproject.
Expand Down Expand Up @@ -50,10 +51,10 @@ internal object ValueClassSupportDsl {
get() = if (!this.isValue_safe) {
throw UnsupportedOperationException("$this is not a value class")
} else {
// value classes always have exactly one property
@Suppress("UNCHECKED_CAST")
valueClassFieldCache.getOrPut(this) {
this.declaredMemberProperties.first().apply { isAccessible = true }
// value classes always have exactly one property with a backing field
this.declaredMemberProperties.first { it.javaField != null }.apply { isAccessible = true }
} as KProperty1<T, *>
}

Expand Down
22 changes: 19 additions & 3 deletions mockk/common/src/test/kotlin/io/mockk/it/ValueClassTest.kt
Expand Up @@ -476,13 +476,27 @@ class ValueClassTest {

assertEquals("example", result)
}
//</editor-fold>
//</editor-fold>

@Test
fun `result value`() {
val givenResult = DummyValue(42)

val mock = mockk<DummyService> {
every { returnValueClass() } returns givenResult
}

val result = mock.returnValueClass()

assertEquals(givenResult, result)
}

companion object {

@JvmInline
value class DummyValue(val value: Int)
value class DummyValue(val value: Int) {
// field without backing field
val text: String get() = value.toString()
}

@JvmInline
value class DummyValueWrapper(val value: DummyValue)
Expand All @@ -501,6 +515,8 @@ class ValueClassTest {
fun argValueClassReturnValueClass(valueClass: DummyValue): DummyValue =
DummyValue(0)

fun returnValueClass(): DummyValue =
DummyValue(0)

fun argNoneReturnsUInt(): UInt = 123u
}
Expand Down

0 comments on commit 6ce0616

Please sign in to comment.