三、 包
首先,你可以看到,JUnit 4使用org.junit.*包而JUnit 3.8使用的是junit.framework.*。当然,为了向后兼容性起见,JUnit 4jar文件发行中加入了这两种包。
四、 继承
在中,测试类不必再扩展junit.framework.TestCase;事实上,它们不必须扩展任何内容。但是,JUnit 4中使用的是注解。为了以一个测试用例方式执行,一个JUnit 4类中至少需要一个@Test注解。例如,如果你仅使用@Before和@After注解而没有至少提供一个@Test方法来编写一个类,那么,当你试图 执行它时将得到一个错误:
java.lang.Exception: No runnable methods.
五、 断言(Assert)方法
因为在JUnit 4中一个测试类并不继承自TestCase(在JUnit 3.8中,这个类中定义了assertEquals()方法),所以你必须使用前缀语法(举例来说,Assert.assertEquals())或者 (由于JDK5.0)静态地导入Assert类。这样以来,你就可以完全象以前一样使用assertEquals方法(举例来说, assertEquals())。
另外,在JUnit 4中,还引入了两个新的断言方法,它们专门用于数组对象的比较。如果两个数组包含的元素都相等,那么这两个数组就是相等的。
public static void assertEquals(String message, Object[] expecteds, Object[] actuals);
public static void assertEquals(Object[] expecteds, Object[] actuals);
由于JDK 5.0的自动装箱机制的出现,原先的12个assertEquals方法全部去掉了。例如,原先JUnit 3.8中的assertEquals(long,long)方法在JUnit 4中要使用assertEquals(Object,Object)。对于assertEquals(byte,byte)、assertEquals (int,int)等也是这样。这种改进将有助于避免反模式。
在JUnit 4中,新集成了一个assert关键字(见我们的例子中的divide()方法)。你可以象使用assertEquals方法一样来使用它,因为它们都抛 出相同的异常(java.lang.AssertionError)。JUnit 3.8的assertEquals将抛出一个junit.framework.AssertionFailedError。注意,当使用assert时, 你必须指定Java的"-ea"参数;否则,断言将被忽略。
六、 预设环境(Fixture)
Fixture是在测试期间初始化和释放任何普通对象的方法。在JUnit 3.8中,你要使用setUp()来实现运行每一个测试前的初始化工作,然后使用tearDown()来进行每个测试后的清理。这两个方法在 TestCase类中都得到重载,因此都被唯一定义。注意,我在这个Setup方法使用的是Java5.0内置的@Override注解-这个注解指示该 方法声明要重载在超类中的方法声明。在JUnit 4中,则代之使用的是@Before和@After注解;而且,可以以任何命名(在我们的例子中是clearCalculator())来调用这些方法。 在本文后面,我将更多地解释这些注解。
七、 测试
JUnit 3.8通过分析它的签名来识别一个测试方法:方法名必须以"test"为前缀,它必须返回void,而且它必须没有任何参数(举例来说, publicvoidtestDivide())。一个不遵循这个命名约定的测试方法将被框架简单地忽略,而且不抛出任何异常(指示发生了一个错误)。
JUnit 4不使用与JUnit 3.8相同的约定。一个测试方法不必以'test'为前缀,但是要使用@Test注解。但是,正如在前一个框架中一样,一个测试方法也必须返回void并 且是无参数的。在JUnit 4中,可以在运行时刻控制这个要求,并且不符合要求的话会抛出一个异常:
java.lang.Exception: Method xxx should have no parameters
java.lang.Exception: Method xxx should be void
@Test注解支持可选参数。它声明一个测试方法应该抛出一个异常。如果它不抛出或者如果它抛出一个与事先声明的不同的异常,那么该测试失败。在我们的例子中,一个整数被零除应该引发一个ArithmeticException异常。
八、 忽略一个测试
记住,不能执行多个方法。然而,如果你不想让测试失败的话,你可以仅仅忽略它。那么,在JUnit 3.8中,我们是如何实现临时禁止一个测试的呢?方法是:通过注释掉它或者改变命名约定,这样测试运行机就无法找到它。在我的例子中,我使用了方法名 notReadyYetTestMultiply()。它没有以"test"开头,所以它不会被识别出来。现在的问题是,在成百上千的测试中间,你可能记 不住重命名这个方法。
在JUnit 4中,为了忽略一个测试,你可以注释掉一个方法或者删除@Test注解(你不能再改变命名约定,否则将抛出一个异常)。然而,该问题将保留:该运行机将不 报告这样一个测试。现在,你可以把@Ignore注解添加到@Test的前面或者后面。测试运行机将报告被忽略的测试的个数,以及运行的测试的数目和运行 失败的测试数目。注意,@Ignore使用一个可选参数(一个String),如果你想记录为什么一个测试被忽略的话。