Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin ObjectCreationException: Unable to create a random instance of type class #481

Open
diego-lima opened this issue Aug 25, 2022 · 0 comments

Comments

@diego-lima
Copy link

I'm trying to use easy-random w/ kotlin 1.7. The scenario I'm about to describe happens with both versions 4.x and 5.x

Consider these statements:

enum class SomeEnum{
    value1,
    value2
}

class Message(
    val code: String,
    val price: Int,
    val someField: SomeEnum
)

class ProductExclusionPolicy : ExclusionPolicy {
    override fun shouldBeExcluded(field: Field, context: RandomizerContext): Boolean {
        return field.name == "price"
    }

    override fun shouldBeExcluded(type: Class<*>?, context: RandomizerContext?): Boolean {
        return false
    }
}

class ProductRandomizerProvider : RandomizerProvider {
    override fun getRandomizerByField(field: Field, context: RandomizerContext): Randomizer<*>? {
        if (field.name == "code") {
            return Randomizer { listOf("213", "377", "465").random() }
        }
    return null
    }
}

These work just fine:

val parameters = EasyRandomParameters()
val easyRandom = EasyRandom(parameters)

val random_message = easyRandom.nextObject(Message::class.java)
println("random_message: ${random_message.code}, ${random_message.price}, ${random_message.someField}")
// random_message: eOMtThyhVNLWUZNRcBaQKxI, -1188957731, value2 
val parameters = EasyRandomParameters()
    .exclusionPolicy(ProductExclusionPolicy())
val easyRandom = EasyRandom(parameters)

val random_message = easyRandom.nextObject(Message::class.java)
println("random_message: ${random_message.code}, ${random_message.price}, ${random_message.someField}")
// random_message: yedUsFwdkelQbxeTeQOvaScfqIOOmaa, 0, value1

If I try to use randomizerProvider, it breaks with ObjectCreationException:

val parameters = EasyRandomParameters()
    .randomizerProvider(ProductRandomizerProvider())
val easyRandom = EasyRandom(parameters)

val random_message = easyRandom.nextObject(Message::class.java)
println("random_message: ${random_message.code}, ${random_message.price}, ${random_message.someField}")
// throws

Stack trace:

Unable to create a random instance of type class Line_2$Message
org.jeasy.random.ObjectCreationException: Unable to create a random instance of type class Line_2$Message
	at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:172)
	at org.jeasy.random.EasyRandom.nextObject(EasyRandom.java:100)
	at Line_5.<init>(Line_5.jupyter-kts:1)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.evalWithConfigAndOtherScriptsResults(BasicJvmScriptEvaluator.kt:105)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke$suspendImpl(BasicJvmScriptEvaluator.kt:47)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke(BasicJvmScriptEvaluator.kt)
	at kotlin.script.experimental.jvm.BasicJvmReplEvaluator.eval(BasicJvmReplEvaluator.kt:49)
	at org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl$eval$resultWithDiagnostics$1.invokeSuspend(InternalEvaluatorImpl.kt:103)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl.eval(InternalEvaluatorImpl.kt:103)
	at org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:71)
	at org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl$execute$1$result$1.invoke(CellExecutorImpl.kt:69)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl.withHost(repl.kt:635)
	at org.jetbrains.kotlinx.jupyter.repl.impl.CellExecutorImpl.execute(CellExecutorImpl.kt:69)
	at org.jetbrains.kotlinx.jupyter.repl.CellExecutor$DefaultImpls.execute$default(CellExecutor.kt:15)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl$evalEx$1.invoke(repl.kt:444)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl$evalEx$1.invoke(repl.kt:433)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl.withEvalContext(repl.kt:397)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl.evalEx(repl.kt:433)
	at org.jetbrains.kotlinx.jupyter.ReplForJupyterImpl.eval(repl.kt:485)
	at org.jetbrains.kotlinx.jupyter.messaging.ProtocolKt$shellMessagesHandler$2$res$1.invoke(protocol.kt:321)
	at org.jetbrains.kotlinx.jupyter.messaging.ProtocolKt$shellMessagesHandler$2$res$1.invoke(protocol.kt:320)
	at org.jetbrains.kotlinx.jupyter.JupyterExecutorImpl$runExecution$execThread$1.invoke(execution.kt:33)
	at org.jetbrains.kotlinx.jupyter.JupyterExecutorImpl$runExecution$execThread$1.invoke(execution.kt:31)
	at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)
Caused by: org.jeasy.random.ObjectCreationException: Unable to create type: int for field: price of class: Line_2$Message
	at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:98)
	at org.jeasy.random.EasyRandom.populateField(EasyRandom.java:209)
	at org.jeasy.random.EasyRandom.populateFields(EasyRandom.java:198)
	at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:165)
	... 35 more
Caused by: org.jeasy.random.ObjectCreationException: Unable to create a random instance of type int
	at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:172)
	at org.jeasy.random.FieldPopulator.generateRandomValue(FieldPopulator.java:160)
	at org.jeasy.random.FieldPopulator.populateField(FieldPopulator.java:93)
	... 38 more
Caused by: java.lang.IllegalArgumentException: Primitive types can't be instantiated in Java
	at org.objenesis.ObjenesisBase.getInstantiatorOf(ObjenesisBase.java:87)
	at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
	at org.jeasy.random.ObjenesisObjectFactory.createNewInstance(ObjenesisObjectFactory.java:78)
	at org.jeasy.random.ObjenesisObjectFactory.createInstance(ObjenesisObjectFactory.java:65)
	at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:147)
	... 40 more

but if I add a specific randomizer for all Int fields, it works again:

class ProductRandomizerProvider : RandomizerProvider {
    override fun getRandomizerByField(field: Field, context: RandomizerContext): Randomizer<*>? {
        if (field.name == "code") {
            return Randomizer { listOf("213", "377", "465").random() }
        }
        if (field.type == Int::class.java) {
            return Randomizer { 10 }
        }
    return null
    }
}
val parameters = EasyRandomParameters()
    .randomizerProvider(ProductRandomizerProvider())
val easyRandom = EasyRandom(parameters)
val random_message = easyRandom.nextObject(Message::class.java)
println("random_message: ${random_message.code}, ${random_message.price}, ${random_message.someField}")
// random_message: 465, 10, value2

Why can't I get away with specifying the randomizer for code field only?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant