简体   繁体   中英

Lombok @NonNull annotation with @Builder not reflecting in test coverage

I have come across an issue while testing lombok annotated class. Description:-

When we annotate a java class(POJO) with @Builder , and have certain instance variable with @NonNull constraints, while writing the test case to check for NullPointerException , we cannot instantiate the POJO with builder and expect it will evaluate against the null check.I delomboked the class and saw that the non null constraint flows inside the generated builder class itself which means a null pointer exception is thrown even before we construct the object.This is a correct behavior in some sense but I needed to know if I can test such a scenario.

@Builder
public class Sample {
    @NonNull
    private final String a;
    private final String b;
}

Now I need to test the case where NullPointerException is thrown in case 'a' is Null. For such a scenario I have 2 options:

  • Either I can create the Sample class with constructor - new Sample(null, null)
  • Or I can create through builder - Sample.builder.a(null).build();

My question is on the second part as first one will work just fine. When I delombok this I will get something like:-

public class Sample {
    @NonNull
    private final String a;
    private final String b;

    Sample(@NonNull String a, String b) {
        this.a = a;
        this.b = b;
    }

    public static SampleBuilder builder() {
        return new SampleBuilder();
    }

    public static class SampleBuilder {
        private @NonNull String a;
        private String b;

        SampleBuilder() {
        }

        public SampleBuilder a(@NonNull String a) {
            this.a = a;
            return this;
        }

        public SampleBuilder b(String b) {
            this.b = b;
            return this;
        }

        public Sample build() {
            return new Sample(a, b);
        }

        public String toString() {
            return "Sample.SampleBuilder(a=" + this.a + ", b=" + this.b + ")";
        }
    }
}

Here if you see NullPointerException will be thrown inside SampleBuilder itself as it takes @NonNull arguments and constructor will never execute the condition to check for non null attribute due to which test coverage will fall.If we use @SuperBuilder , this will not happen as it does not take @NonNull in builder arguments.

Not really sure what you are expecting, but the source code below can properly test the null check of both constructor and builder of Sample class.

You can see it running at https://repl.it/repls/CleverWiryTruespace .

import lombok.NonNull;
import lombok.Builder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Before;
import org.junit.rules.ExpectedException;
import org.junit.runner.JUnitCore;

class Main {
  @Builder
  public static class Sample {
      @NonNull
      private final String a;
      private final String b;
  }

  public static class TestSample {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Before
    public void setUp() {
      thrown.expect(NullPointerException.class);
      thrown.expectMessage("a is marked non-null but is null");
    }

    @Test
    public void test1() {
      Sample s = new Sample(null, "abc");
    }

    @Test
    public void test2() {
      Sample.builder().a(null).build();
    }
  }

  public static void main(String[] args) {
    new JUnitCore().main(TestSample.class.getName());
  }
}

From the code we can see that if we want to trigger NPE at constructor level we need to leave the @NonNull parameter as empty rather than setting it to null which will trigger builder method level NPE. If I build Sample object in the following manner it should suffice my case:-

Sample sample = Sample.builder.b("b").build();

Here I am not explicitly setting parameter 'a' to NULL if I want to test NPE of 'a' at constructor level.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM