繁体   English   中英

带有@Builder 的Lombok @NonNull 注释未反映在测试覆盖率中

[英]Lombok @NonNull annotation with @Builder not reflecting in test coverage

我在测试带注释的class时遇到了一个问题。 描述:-

当我们使用 @Builder 注释 java 类(POJO),并且具有带有@Builder约束的某些实例变量@NonNull ,在编写测试用例以检查NullPointerException时,我们无法使用 builder 实例化POJO ,并期望它会根据 null 检查进行评估。 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这样的场景。

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

现在我需要测试在“a”是 Null 的情况下抛出 NullPointerException 的情况。 对于这种情况,我有 2 个选项:

  • 我可以使用构造函数创建示例 class - new Sample(null, null)
  • 或者我可以通过构建器创建 - Sample.builder.a(null).build();

我的问题在第二部分,因为第一个可以正常工作。 当我delombok时,我会得到类似的东西:-

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 + ")";
        }
    }
}

在这里,如果您看到 NullPointerException 将被抛出 SampleBuilder 本身,因为它需要@NonNull arguments 并且构造函数将永远不会执行条件来检查非 null 属性,因为测试覆盖率将会下降。如果我们使用@SuperBuilder ,这将不会发生在构建器 arguments 中不采用@NonNull

不太确定您在期待什么,但下面的源代码可以正确测试示例 class 的构造函数和生成器的null检查。

您可以看到它在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());
  }
}

从代码中我们可以看到,如果我们想在构造函数级别触发 NPE,我们需要将 @NonNull 参数保留为空,而不是将其设置为 null,这将触发构建方法级别的 NPE。 如果我以下列方式构建样本 object 就足够了:-

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

如果我想在构造函数级别测试“a”的 NPE,这里我没有将参数“a”显式设置为 NULL。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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