fixture-monkey icon indicating copy to clipboard operation
fixture-monkey copied to clipboard

NullPointerException: Parameter specified as non-null is null

Open Sti2nd opened this issue 1 year ago • 6 comments

Describe the bug

Sometimes tests crashes with the error message: Parameter specified as non-null is null: method my.namespace.entity.DataEntity.<init>, parameter dataSet. Likely because FixtureMonkey tries to put null in a non-nullable field.

Parameter specified as non-null is null: method my.namespace.entity.DataEntity.<init>, parameter dataSet
java.lang.NullPointerException: Parameter specified as non-null is null: method my.namespace.entity.DataEntity.<init>, parameter dataSet
	at my.namespace.entity.DataEntity.<init>(DataEntity.kt)
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at kotlin.reflect.jvm.internal.calls.CallerImpl$Constructor.call(CallerImpl.kt:41)
	at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod$kotlin_reflection(KCallableImpl.kt:207)
	at kotlin.reflect.jvm.internal.KCallableImpl.callBy(KCallableImpl.kt:112)
	at com.navercorp.fixturemonkey.kotlin.introspector.PrimaryConstructorArbitraryIntrospector.introspect$lambda$3(PrimaryConstructorArbitraryIntrospector.kt:72)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.combined(ObjectCombinableArbitrary.java:54)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.lambda$combined$0(ObjectCombinableArbitrary.java:51)
	at java.base/java.util.HashMap.forEach(HashMap.java:1429)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.combined(ObjectCombinableArbitrary.java:50)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.FilteredCombinableArbitrary.combined(FilteredCombinableArbitrary.java:73)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at com.navercorp.fixturemonkey.api.arbitrary.ContainerCombinableArbitrary.combined(ContainerCombinableArbitrary.java:48)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.lambda$combined$0(ObjectCombinableArbitrary.java:51)
	at java.base/java.util.HashMap.forEach(HashMap.java:1429)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.combined(ObjectCombinableArbitrary.java:50)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.FilteredCombinableArbitrary.combined(FilteredCombinableArbitrary.java:73)
	at com.navercorp.fixturemonkey.resolver.ResolvedCombinableArbitrary.combined(ResolvedCombinableArbitrary.java:77)
	at com.navercorp.fixturemonkey.resolver.DefaultArbitraryBuilder.sample(DefaultArbitraryBuilder.java:489)
	at com.navercorp.fixturemonkey.FixtureMonkey.lambda$giveMe$2(FixtureMonkey.java:154)
	at java.base/java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1367)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMe(FixtureMonkey.java:162)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMeOne(FixtureMonkey.java:170)
	at DataServiceTest.getData should return data(DataServiceTest.kt:373)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

Your environment

  • 1.0.22
  • Kotlin 2.0.0 on JVM 21

Steps to reproduce

Set up a code base with JPA and run the following example code. (Perhaps JPA is not needed to reproduce, I just mention it because we use it)

@Entity
class DataEntity(
  @OneToMany(fetch = FetchType.LAZY, cascade = [CascadeType.ALL], mappedBy = "data")
  val dataSet: MutableSet<DataSourceEntity> = mutableSetOf(),
)

@Entity
class DataSourceEntity(
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "data")
    val data: DataEntity? = null,
)


class DataServiceTest {
  val fixture: FixtureMonkey =
      FixtureMonkey
          .builder()
          .plugin(KotlinPlugin())
          .plugin(
              JqwikPlugin().javaTypeArbitraryGenerator(
                  object : JavaTypeArbitraryGenerator {
                      override fun strings(): StringArbitrary = Arbitraries.strings().alpha()
                  },
              ),
          ).build()

  @Test
  fun `getData should return data`() {
      // Arrange
      val dataEntity = fixture.giveMeOne(DataEntity::class.java) // Problem here
      assertEquals(1, 1) // Always true
  }
}

At first I thought it might have to do with the circular reference. However I have tried to make DataSourceEntity.data non-nullable, and can still reproduce.

Expected behaviour

Test should run successfully

Actual behaviour

Test fails because of NullPointerException

Sti2nd avatar Aug 05 '24 07:08 Sti2nd

@Sti2nd Hello, thank you for reporting an issue.

It'll be fixed in 1.0.23. Let you know when 1.0.23 is released.

Thank you.

seongahjo avatar Aug 07 '24 05:08 seongahjo

@Sti2nd Hello, 1.0.23 is released.

Please check to see if the problem has been resolved.

Thank you.

seongahjo avatar Aug 10 '24 10:08 seongahjo

@seongahjo Hi, thank you for your effort! I now get the following error, at least it is different :)

Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "writeMethod" is null
java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "writeMethod" is null
	at com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector.lambda$null$1(BeanArbitraryIntrospector.java:109)
	at java.base/java.util.HashMap.forEach(HashMap.java:1429)
	at com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector.lambda$combine$2(BeanArbitraryIntrospector.java:100)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.combined(ObjectCombinableArbitrary.java:54)
	at com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitraryDelegator.combined(CombinableArbitraryDelegator.java:34)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.lambda$combined$0(ObjectCombinableArbitrary.java:51)
	at java.base/java.util.HashMap.forEach(HashMap.java:1429)
	at com.navercorp.fixturemonkey.api.arbitrary.ObjectCombinableArbitrary.combined(ObjectCombinableArbitrary.java:50)
	at com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitraryDelegator.combined(CombinableArbitraryDelegator.java:34)
	at com.navercorp.fixturemonkey.api.arbitrary.NullInjectCombinableArbitrary.combined(NullInjectCombinableArbitrary.java:46)
	at com.navercorp.fixturemonkey.api.arbitrary.TraceableCombinableArbitrary.combined(TraceableCombinableArbitrary.java:42)
	at com.navercorp.fixturemonkey.api.arbitrary.FilteredCombinableArbitrary.combined(FilteredCombinableArbitrary.java:73)
	at com.navercorp.fixturemonkey.resolver.ResolvedCombinableArbitrary.combined(ResolvedCombinableArbitrary.java:77)
	at com.navercorp.fixturemonkey.resolver.DefaultArbitraryBuilder.sample(DefaultArbitraryBuilder.java:489)
	at com.navercorp.fixturemonkey.FixtureMonkey.lambda$giveMe$2(FixtureMonkey.java:154)
	at java.base/java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1367)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMe(FixtureMonkey.java:162)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMeOne(FixtureMonkey.java:170)
	at DataServiceTest.getData should return data(DataServiceTest.kt:480)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

Sti2nd avatar Aug 20 '24 13:08 Sti2nd

@Sti2nd Hello. Are you generating a Kotlin type? If so, you should add KotlinPlugin. Maybe, you have misused the ArbitraryIntrospector. Please check it!

Thank you.

seongahjo avatar Aug 23 '24 07:08 seongahjo

I am using the KotlinPlugin, but not sure if we generate a Kotlin type (or what you mean). The last time I ran the code I ran it without JqwikPlugin().javaTypeArbitraryGenerator. So I guess then we are not using ArbitraryIntrospector?

Fixture Monkey only crashes for entities in our project. Perhaps JPA is the source of the problem after all. We also use Spring Boot, if that information helps.

Thank you for your replies.

Sti2nd avatar Aug 27 '24 10:08 Sti2nd

@Sti2nd Hi, please add the InterfacePlugin option.

plugin(InterfacePlugin().useAnonymousArbitraryIntrospector(false))

Please let me know if you still have the problem.

seongahjo avatar Aug 28 '24 04:08 seongahjo