2009-11-25 281 views
27

启用类的断言我已经有点几次通过,因为断言没有在JUnit的JVM实例启用未在JUnit测试套件失败的Java assert语句。要清楚的是,这些是实现内部的“黑盒子”断言(检查不变量等),而不是JUnit测试自己定义的断言。当然,我想在测试套件中发现任何这样的断言失败。的JUnit:测试

明显的解决方案是要非常小心使用-enableassertions每当我运行JUnit,但我更喜欢一个更强大的解决方案。一种替代方法是将以下测试添加到每个测试类别中:

@Test(expected=AssertionError.class) 
    public void testAssertionsEnabled() { 
    assert(false); 
    } 

是否有更自动的方法来完成此操作? JUnit的系统范围配置选项?我可以在setUp()方法中进行动态调用?

+1

只是一个一般性的问题时。如果你真的想彻底的单元测试你的代码,你不应该测试启用和不启用断言吗?有一件事断言是**非常好**,因为引入了意想不到的副作用。 – 2009-11-25 16:33:59

+0

btw。你如何运行JUnit测试用例?如果你有一些build manager(ant,maven),默认添加这个开关应该是微不足道的。 – jitter 2009-11-25 16:41:45

+0

@Alexander:这不是一个坏主意。 @jitter:当然你是对的。 Maven似乎默认启用断言。在此之前,我没有注意到Eclipse有一个偏好设置。问题是这些设置可以改变你的背后...... – 2009-11-25 17:03:52

回答

5

我提出了三种可能的(简单吗?)修复它为我工作快速测试后(但你可能需要检查使用静态初始化块的副作用)

1)添加静态-initializer块那些依靠断言测试用例被启用

import .... 
public class TestXX.... 
... 
    static { 
     ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 
    } 
    ... 
    @Test(expected=AssertionError.class) 
    ... 
... 

2)创建一个基类,所有测试类的扩展这就需要断言启用

public class AssertionBaseTest { 
    static { 
     //static block gets inherited too 
     ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 
    } 
} 

3)创建它运行所有测试

import org.junit.runner.RunWith; 
import org.junit.runners.Suite; 

@RunWith(Suite.class) 
@Suite.SuiteClasses({ 
    //list of comma-separated classes 
    /*Foo.class, 
    Bar.class*/ 
}) 
public class AssertionTestSuite { 
    static { 
     //should run before the test classes are loaded 
     ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 
    } 
    public static void main(String args[]) { 
     org.junit.runner.JUnitCore.main("AssertionTestSuite"); 
    } 
} 
+0

+1非常酷的隐藏Java宝石。 – 2009-11-25 16:33:11

+1

这在我的情况下不起作用。它依赖于类加载的顺序。 – 2009-11-25 16:33:15

+2

对不起,但这不会按预期工作。加载和初始化类时必须启用断言,并且在类加载器上设置默认断言状态只会影响稍后加载的类。 – jarnbjo 2009-11-25 16:33:55

1

作为我的一个朋友测试套件说......为什么需要写一个断言的时间,如果你只是把它关掉?

鉴于逻辑所有断言语句应该成为:

if(!(....)) 
{ 
    // or some other appropriate RuntimeException subclass 
    throw new IllegalArgumentException("........."); 
} 

要回答你的问题,你可能想:-)

import org.junit.BeforeClass; 
import org.junit.runner.RunWith; 
import org.junit.runners.Suite; 


@RunWith(Suite.class) 
@Suite.SuiteClasses({ 
     FooTest.class, 
     BarTest.class 
     }) 
public class TestSuite 
{ 
    @BeforeClass 
    public static void oneTimeSetUp() 
    { 
     ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 
    } 
} 

然后运行测试套件,而不是每个测试的方式。这应该(在我的测试中工作,但我没有阅读JUnit框架代码的内部结果)会导致在加载任何测试类之前设置断言状态。

+0

除非断言被证明会减慢代码的速度,否则它就会成为一个问题,我宁愿让它们一直存在。先决条件/后置条件和任何其他类型的断言陈述 - 如果你花时间写它为什么把它关掉? – TofuBeer 2009-11-25 18:08:54

+0

如果它是一个先决条件,然后我的理由是,这是不值得的断言,并应进行检查,并抛出一个IllegalArgumentException或任何适当的异常是针对前提。后置条件完全值得断言,假设它检查的东西超过@NotNull。 – Trejkaz 2012-09-27 04:29:02

+0

对于私有方法,断言仍然有用,您想在开发过程中检查前提条件,但在生产中不检查前提条件。在公共接口上使用例外,除非有很好的理由不这样做。 – SigmaX 2014-02-19 03:13:33

21

在Eclipse中,你可以去WindowsPreferencesJavaJUnit,其中有一个选项添加-ea每次创建一个新的启动配置。它也将-ea选项添加到调试配置中。

全文旁边复选框

添加“电子艺界”到VM参数创建一个新的JUnit启动 配置

+0

你在Eclipse中是否有任何一种单元测试插件?我无法找到该选项。 – 2012-04-06 07:41:17

+0

不,它是标准Eclipse安装的一部分 – RAbraham 2012-04-11 12:55:05

+0

您使用的是哪个版本的Eclipse? – 2012-04-11 14:58:35