带有@Builder 的 Lombok @NonNull 注释未反映在测试覆盖率中
Lombok @NonNull annotation with @Builder not reflecting in test coverage
我在测试 lombok 注释 class 时遇到了一个问题。
说明:-
当我们用@Builder
注解一个javaclass(POJO),并且有某个实例变量带有@NonNull
约束,同时编写测试用例来检查NullPointerException
,我们不能用构建器实例化 POJO 并期望它将针对空值 check.I 进行评估 class 并看到非空约束在生成的构建器 class 本身内部流动,这意味着甚至在我们构建 object.This 之前抛出空指针异常在某种意义上是正确的行为,但我需要知道我是否可以测试这种情况。
@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();
我的问题是关于第二部分的,因为第一部分可以正常工作。
当我删除这个时,我会得到类似的东西:-
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
个参数,并且构造函数将永远不会执行检查非 null 属性的条件,因为测试覆盖率将 fall.If 我们使用 @SuperBuilder
,这不会发生,因为它不会在构建器参数中使用 @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。
如果我以下列方式构建 Sample 对象,它应该足以满足我的情况:-
Sample sample = Sample.builder.b("b").build();
如果我想在构造函数级别测试 'a' 的 NPE,这里我没有明确地将参数 'a' 设置为 NULL。
我在测试 lombok 注释 class 时遇到了一个问题。 说明:-
当我们用@Builder
注解一个javaclass(POJO),并且有某个实例变量带有@NonNull
约束,同时编写测试用例来检查NullPointerException
,我们不能用构建器实例化 POJO 并期望它将针对空值 check.I 进行评估 class 并看到非空约束在生成的构建器 class 本身内部流动,这意味着甚至在我们构建 object.This 之前抛出空指针异常在某种意义上是正确的行为,但我需要知道我是否可以测试这种情况。
@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();
我的问题是关于第二部分的,因为第一部分可以正常工作。 当我删除这个时,我会得到类似的东西:-
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
个参数,并且构造函数将永远不会执行检查非 null 属性的条件,因为测试覆盖率将 fall.If 我们使用 @SuperBuilder
,这不会发生,因为它不会在构建器参数中使用 @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。 如果我以下列方式构建 Sample 对象,它应该足以满足我的情况:-
Sample sample = Sample.builder.b("b").build();
如果我想在构造函数级别测试 'a' 的 NPE,这里我没有明确地将参数 'a' 设置为 NULL。