ReflectionException exception for a simple Counter class
nagkumar opened this issue · 7 comments
com.pholser.junit.quickcheck.internal.ReflectionException: com.pholser.junit.quickcheck.internal.ReflectionException: java.lang.InstantiationException: com.tejasoft.utils.Counter
at app//com.pholser.junit.quickcheck.internal.Reflection.reflectionException(Reflection.java:302)
at app//com.pholser.junit.quickcheck.internal.Reflection.instantiate(Reflection.java:130)
at app//com.pholser.junit.quickcheck.internal.ParameterTypeContext.makeGenerator(ParameterTypeContext.java:283)
at app//com.pholser.junit.quickcheck.internal.ParameterTypeContext.addGenerators(ParameterTypeContext.java:265)
at app//com.pholser.junit.quickcheck.internal.ParameterTypeContext.annotate(ParameterTypeContext.java:225)
at app//com.pholser.junit.quickcheck.internal.PropertyParameterContext.annotate(PropertyParameterContext.java:51)
at app//com.pholser.junit.quickcheck.runner.PropertyStatement.parameterContextFor(PropertyStatement.java:187)
at app//com.pholser.junit.quickcheck.runner.PropertyStatement.lambda$evaluate$0(PropertyStatement.java:93)
at java.base@19.0.2/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base@19.0.2/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1006)
at java.base@19.0.2/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base@19.0.2/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base@19.0.2/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base@19.0.2/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base@19.0.2/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at app//com.pholser.junit.quickcheck.runner.PropertyStatement.evaluate(PropertyStatement.java:101)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at app//org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at app//org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:42)
at app//org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
at app//org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:72)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at app//org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
at java.base@19.0.2/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base@19.0.2/java.lang.reflect.Method.invoke(Method.java:578)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Wrap lines
Where counter is
package com.tejasoft.utils;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import static com.tejasoft.utils.GenConsts.EMPTY_STRING;
import static com.tejasoft.utils.GenConsts.ZERO_INT;
import static com.tejasoft.utils.StringHelper.normalize;
public final class Counter implements Serializable
{
private final AtomicInteger counter = new AtomicInteger();
private final String name;
public Counter(final String aName)
{
this(aName, ZERO_INT);
}
public Counter(final String aName, int aInitialValue)
{
name = normalize(aName);
counter.set(aInitialValue);
}
public final String getName()
{
return name;
}
public final Counter increment()
{
counter.getAndIncrement();
return this;
}
public final int getCount()
{
return counter.get();
}
@Override
public final String toString()
{
int ckt = getCount();
return (ckt > 0) ? "Total '" + name + "' Count: " + ckt : EMPTY_STRING;
}
}
and test case is
package com.tejasoft.utils.tests.ju.ju4.ut.propt.jqt;
import com.pholser.junit.quickcheck.From;
import com.pholser.junit.quickcheck.Property;
import com.pholser.junit.quickcheck.generator.Fields;
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck;
import com.tejasoft.utils.Counter;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
@RunWith(JUnitQuickcheck.class)
public final class TestJUQCounter
{
@Property
public final void incrementing(@From(Fields.class) final Counter aCounter)
{
int count = aCounter.getCount();
assertEquals(count + 1, aCounter.increment().getCount());
}
}
Is AtomicInteger
integer supported..
Further guess work revealed that it is unable to create a counter class with there is no zero-argument constructor that is public.
public Counter()
{
this("");
}
I added this to counter method, then test case worked..
Need for public zero argument is a serious limitation of this framework also, its engine is still junit 4 not upgraded to junit 5..
@nagkumar Thanks for this. Without some help and a serious increase in free time, It's unlikely that I'm going to revamp junit-quickcheck for JUnit 5. See #139.
Without a zero-arg constructor on Counter
, how would you propose to tell the Fields
generator how to instantiate the Counter
class? Perhaps you might use @From(Ctor.class)
instead of @From(Fields.class)
.
AtomicInteger
and kin from java.util.concurrent
are not supported out of the box. To have default generators in junit-quickcheck for them sounds like a reasonable request. In the meantime, you can create generators for these types on your own, and make them available for junit-quickcheck to discover. See https://pholser.github.io/junit-quickcheck/site/1.0/usage/other-types.html for help in doing this.
Would you mind to create a separate issue requesting support for java.util.concurrent.Atomic{Integer,Boolean,Long}
?
Perhaps you might use @from(Ctor.class) instead of @from(Fields.class).
It ends up with this error message..
X incrementing
com.pholser.junit.quickcheck.internal.ReflectionException: com.pholser.junit.quickcheck.internal.ReflectionException: class com.tejasoft.utils.Counter needs a single accessible constructor
Would you mind to create a separate issue requesting support for
java.util.concurrent.Atomic{Integer,Boolean,Long}?
When I add a default empty constructor in the Counter class even an atomic integer works...
@nagkumar If you use Fields
, there needs to be an accessible zero-arg constructor on the class representing the annotated parameter.
If you use Ctor, you need a single accessible constructor.
If you create a custom generator for your class, it can instantiate your class in whatever manner it pleases.
What change(s) to junit-quickcheck are you requesting?
What change(s) to junit-quickcheck are you requesting?
If you use Ctor, you need a single accessible constructor.
I have multiple constructors, can I not specify which one to use
What change(s) to junit-quickcheck are you requesting?
If you use Ctor, you need a single accessible constructor.
I have multiple constructors, can I not specify which one to use
No, you cannot. Your best bet is to make a generator for your class, and make junit-quickcheck aware of it. junit-quickcheck comes with a number of generators that you can use as a model.