gpt4 book ai didi

groovy - JUnit Assume.assumeNotNull 抛出空指针而不是跳过测试

转载 作者:行者123 更新时间:2023-12-02 00:56:56 67 4
gpt4 key购买 nike

我在 groovy 中有这个 junit(使用 JUnit 4.12)测试,只有在 getenv != null 时才应该执行:

    import org.junit.Assume
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
...
@Test
public void skipWhenNull() throws Exception {
def getenv = System.getenv("bogos")
if( getenv == null) {
println "Its null!"
}
Assume.assumeNotNull(getenv);
println "Test executing!"
}

但是当我运行测试时它打印:Its null! 然后抛出 NullPointer 异常(在行中:Assume.assumeNotNull(getenv);)。 Assume.assumeNotNull(expr) 的意义不是说当 expr 计算为 null 而不是抛出 Nullpointer 时它会跳过测试吗?

最佳答案

我认为这可能是一个错误,但我认为这更像是 Groovy 动态类型系统在其默认行为中的结果。 Assume.assumeNotNull(Object... objects) 方法使用可变参数。这意味着在传递非数组元素的情况下,编译器会将其包装在预期类型的​​数组中。

String getenv = System.getenv("bogos"); 

Assume.assumeNotNull(getenv); // --> Assume.assumeNotNull(new Object[] { getenv });

这就是 Java 的静态编译器所做的。所以在 getenv == null 的情况下,我们最终得到:

Assume.assumeNotNull(new Object[] { null });

包含单个 null 元素的非空数组。另一方面,如果我们指定一个数组类型的变量,并为其分配一个null值,调用相同的方法将导致NullPointerException,就像下面的示例:

String[] array = null;

Assume.assumeNotNull(array); // --> throws NPE

至少在 Java 中是这样的。现在,为什么它在 Groovy 单元测试中失败了?默认情况下,Groovy 是一种动态类型语言,因此它在这方面的表现完全不同。似乎 Groovy 的类型系统将 null 值应用于方法类型而不将其包装在数组中,因此在将 null 传递给期望例如的方法的情况下Object... objects 我们总是得到 objects == null 而不是 objects == new Object[] { null }

我开始质疑自己这是不是一个错误。从一个角度来看,我希望动态 Groovy 的行为方式与静态编译代码的行为方式相同。但另一方面,在动态类型系统中,这种区别是可以接受的(甚至可能是可取的),因为动态类型系统在运行时推断类型。它看到 null,因此它认为我们打算将 null 值分配给 Object[] 类型的变量。

解决方案

有两种方法可以解决这个问题。

1。启用静态编译

如果您不在测试用例中使用 Groovy 的动态和元编程功能,您可以轻松地使用 @groovy.transform.CompileStatic 注释对其进行注释,以生成更类似于 Java 字节码的字节码。例如,这是动态 Groovy 中方法的字节码:

@Test
public void skipWhenNull() throws Exception {
CallSite[] var1 = $getCallSiteArray();
Object getenv = var1[4].call(System.class, "bogos");
if (ScriptBytecodeAdapter.compareEqual(getenv, (Object)null)) {
var1[5].callCurrent(this, "Its null!");
}

var1[6].call(Assume.class, getenv);
var1[7].callCurrent(this, "Test executing!");
}

这里是相同的方法,但从字节码的角度用 @CompileStatic 注释:

@Test
public void skipWhenNull() throws Exception {
String getenv = System.getenv("bogos");
Object var10000;
if (getenv == null) {
DefaultGroovyMethods.println(this, "Its null!");
var10000 = null;
}

Assume.assumeNotNull(new Object[]{getenv});
var10000 = null;
DefaultGroovyMethods.println(this, "Test executing!");
var10000 = null;
}

2。用数组包裹 getenv

或者,您可以更明确地调用 Assume.assumeNotNull 方法。如果您更换:

Assume.assumeNotNull(getenv);

与:

Assume.assumeNotNull([getenv] as Object[]);

然后您将使用 Object[] 数组显式包装参数,并且您将阻止传递由 null 表示的数组对象,而是传递包含 的单个元素数组code>null 值代替。

关于groovy - JUnit Assume.assumeNotNull 抛出空指针而不是跳过测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53650903/

67 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com