- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 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[]
类型的变量。
有两种方法可以解决这个问题。
如果您不在测试用例中使用 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;
}
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/
我在 groovy 中有这个 junit(使用 JUnit 4.12)测试,只有在 getenv != null 时才应该执行: import org.junit.Assume imp
我有一个实用程序类,它采用存储库类接口(interface)的构造函数参数。然后将其分配给类(class)中的私有(private)字段。在类的各种方法中,我引用这个私有(private)接口(int
我是一名优秀的程序员,十分优秀!