Describe the bug
When a pre-built object (created via giveMeKotlinBuilder(...).sample()) is assigned to a
parent's property using set() / setExp(), Fixture Monkey decomposes and regenerates that
object. As a result, a @JvmInline value class field loses the value that was fixed on it
— it is regenerated to a random value — while plain (non-value-class) fields of the same object
are preserved.
This is a behavior change: it works as expected on 1.1.15 and breaks starting from 1.1.16
(still reproduces on 1.1.20). It does not appear to be mentioned in the release notes.
Wrapping the value with Values.just(...) works around it, but the change silently breaks
existing tests that relied on the previous "use the instance as-is" behavior.
Your environment
- Fixture Monkey: 1.1.16 (first broken version; also reproduces on 1.1.20). Works correctly on 1.1.14, 1.1.15. Artifact:
fixture-monkey-starter-kotlin
- Kotlin: 2.1.10
- Java/JVM target: 17
Steps to reproduce
Run the following Kotlin test. The failure is deterministic (the value class field is always
regenerated), so it reproduces on every run regardless of seed.
import com.navercorp.fixturemonkey.FixtureMonkeyBuilder
import com.navercorp.fixturemonkey.kotlin.KotlinPlugin
import com.navercorp.fixturemonkey.kotlin.giveMeKotlinBuilder
import kotlin.test.assertEquals
import org.junit.Test
class FmValueClassReproTest {
@JvmInline
value class Code(val value: String)
data class Child(val code: Code, val name: String)
data class Parent(val child: Child)
private val fm = FixtureMonkeyBuilder().plugin(KotlinPlugin()).build()
// A) set & assert the VALUE CLASS field
@Test
fun valueClassField() {
val fixedCode = Code("FIXED")
val child = fm.giveMeKotlinBuilder<Child>()
.setExp(Child::code, fixedCode)
.sample()
assertEquals(fixedCode, child.code) // standalone
val parent = fm.giveMeKotlinBuilder<Parent>()
.setExp(Parent::child, child)
.sample()
println("Check. parent.child: ${parent.child}, child: $child")
assertEquals(fixedCode, parent.child.code) // hypothesis: FAIL on 1.1.16
}
// B) set & assert a PLAIN field (object still contains a value class field)
@Test
fun plainFieldInValueClassObject() {
val child = fm.giveMeKotlinBuilder<Child>().setExp(Child::name, "FIXED").sample()
val parent = fm.giveMeKotlinBuilder<Parent>().setExp(Parent::child, child).sample()
println("DIAG name=${parent.child.name}")
assertEquals("FIXED", parent.child.name)
}
}
Expected behaviour
parent.child.code should remain Code("FIXED") — the value fixed on the injected instance's
value class field should be preserved when the object is set into a parent (as it was in 1.1.15,
and as plain fields still are in 1.1.16+).
Actual behaviour
parent.child.code is regenerated to a random Code(...), so the assertion fails. Only the
@JvmInline value class field is affected; plain fields (e.g. name) of the same object are
preserved. Wrapping with Values.just(child) restores the correct value.
Describe the bug
When a pre-built object (created via
giveMeKotlinBuilder(...).sample()) is assigned to aparent's property using
set()/setExp(), Fixture Monkey decomposes and regenerates thatobject. As a result, a
@JvmInline value classfield loses the value that was fixed on it— it is regenerated to a random value — while plain (non-value-class) fields of the same object
are preserved.
This is a behavior change: it works as expected on 1.1.15 and breaks starting from 1.1.16
(still reproduces on 1.1.20). It does not appear to be mentioned in the release notes.
Wrapping the value with
Values.just(...)works around it, but the change silently breaksexisting tests that relied on the previous "use the instance as-is" behavior.
Your environment
fixture-monkey-starter-kotlinSteps to reproduce
Run the following Kotlin test. The failure is deterministic (the value class field is always
regenerated), so it reproduces on every run regardless of seed.
Expected behaviour
parent.child.code should remain Code("FIXED") — the value fixed on the injected instance's
value class field should be preserved when the object is set into a parent (as it was in 1.1.15,
and as plain fields still are in 1.1.16+).
Actual behaviour
parent.child.code is regenerated to a random Code(...), so the assertion fails. Only the
@JvmInline value class field is affected; plain fields (e.g. name) of the same object are
preserved. Wrapping with Values.just(child) restores the correct value.