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

NPE occurs in a class with a specific property #762

Closed
kjh5833 opened this issue Sep 21, 2023 · 2 comments
Closed

NPE occurs in a class with a specific property #762

kjh5833 opened this issue Sep 21, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@kjh5833
Copy link

kjh5833 commented Sep 21, 2023

Describe the bug

안녕하세요! 라이브러리 잘 사용하고 있습니다.
테스트 작성 중 특정 필드(mHeader, isGlobal)를 가진 class 들에서 NPE 가 발생하고,
정상동작 하지 않아 이슈를 올리게 되었습니다.
이유 및 회피 방안이 있는지 궁금합니다.

--

We have a little problem.
NPE occurs in a class with a specific field(mHeader, isGlobal).
I wonder if there is a reason or a way to avoid this.

Your environment

  • 0.6.3
  • 8

Steps to reproduce

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Valid {

    private String mheader;
    private boolean isglobal;
}

@Getter
@Setter
@ToString
public class Invalid {

    private String mHeader;
    private boolean isGlobal;
}
class FixtureTest extends Specification {

// 통과
    def 'Valid test'() {
        given:
        def given = FixtureMonkey.create().giveMeOne(Valid.class)

        when:
        System.out.println("given :: " + given)

        then:
        noExceptionThrown()
    }

// 실패
    def 'Invalid test'() {
        given:
        def given = FixtureMonkey.create().giveMeOne(Invalid.class)

        when:
        System.out.println("given :: " + given)

        then:
        noExceptionThrown()
    }
}

Expected behaviour

Test PASS

Actual behaviour

NPE occurred

java.lang.NullPointerException
	at com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector.lambda$null$0(BeanArbitraryIntrospector.java:76)
	at java.base/java.util.HashMap.forEach(HashMap.java:1337)
	at com.navercorp.fixturemonkey.api.introspector.BeanArbitraryIntrospector.lambda$combine$1(BeanArbitraryIntrospector.java:70)
	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.resolver.ArbitraryResolver$1.combined(ArbitraryResolver.java:115)
	at com.navercorp.fixturemonkey.api.arbitrary.FilteredCombinableArbitrary.combined(FilteredCombinableArbitrary.java:68)
	at com.navercorp.fixturemonkey.resolver.DefaultArbitraryBuilder.sample(DefaultArbitraryBuilder.java:420)
	at com.navercorp.fixturemonkey.FixtureMonkey.lambda$giveMe$2(FixtureMonkey.java:166)
	at java.base/java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1360)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMe(FixtureMonkey.java:174)
	at com.navercorp.fixturemonkey.FixtureMonkey.giveMeOne(FixtureMonkey.java:182)
	at com.중략.FixtureTest.Invalid test(FixtureTest.groovy:23)
@kjh5833 kjh5833 added the bug Something isn't working label Sep 21, 2023
@seongahjo
Copy link
Contributor

seongahjo commented Sep 21, 2023

@kjh5833 님 안녕하세요.

create를 통해 생성한 Fixture Monkey 인스턴스는 기본 BeanArbitraryIntrospector를 사용해 객체를 생성합니다.
BeanArbitraryIntrospector에서는 빈 생성자setter를 사용해 객체를 만들고 있습니다.
setter를 찾을 때 JavaBeans 스펙을 기준으로 조회하고 있습니다. 따라서 isGlobal인 필드는 setter의 이름이 setIsGlobal 이여야 하고, mHeadersetmHeader 이여야 합니다. 참조1 참조2

기본적인 롬복 설정에서는 isGlobal의 setter를 setGlobal, mHeader의 setter를 setMHeader로 생성합니다. 이런 이유로, 현재 setter를 못찾아서 NPE가 나고 있습니다.

해결방안은 두 가지가 있을 것 같습니다.

첫 번째 해결방안

다른 ArbitraryIntrospector를 사용한다. 지금 보여주신 객체의 예만 봤을 때는 FieldReflectionArbitraryIntrospector가 적합해보입니다.

다음과 같이 설정하시면 ArbitraryIntrospector를 변경할 수 있습니다.

FixtureMonkey.builder()
	.objectIntrospector(FieldReflectionArbitraryIntrospector.INSTANCE)
	.build();

ArbitraryIntrospector에 대한 설명과 종류는 문서를 참조해주세요.

두 번째 해결방안

롬복 설정을 추가한다.

  1. lombok.config에 lombok.accessors.javaBeansSpecCapitalization=true를 추가한다.
  2. isGlobal 필드에 @Accessors(fluent=true)를 사용한다.

세 번째 해결방안

필드의 이름을 JavaBeans에 맞게 변경한다.

시도해보시고, 문제가 있으면 다시 질문 주세요.
감사합니다~~

@kjh5833
Copy link
Author

kjh5833 commented Sep 21, 2023

@seongahjo 님 안녕하세요!
원인 및 여러 해결방안까지 정확한 답변 감사드립니다~!
첫번째 방안으로 해결하였습니다! 감사합니다!

@kjh5833 kjh5833 closed this as completed Sep 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants