JUnit4 使用指南二 (熟练掌握)

上一章节中我们只是简单的介绍了下在Eclipse中使用JUnit4的简要过程,这一章节中,我们首先简要的比较下JUnit4与JUnit3的不同之处,然后详细的分析JUnit4常用的一些特性,掌握它们对灵活编写单元测试代码会非常有帮助。

1. JUnit4 与 JUnit3 的区别

上一章节中,我们写了一个Calculator的TestCase ”CalculatorTest“,我们分别来看一下JUnit3与JUnit4的代码实现:

JUnit3的实现

package com.rigel.ut;

import org.junit.Assert;
import junit.framework.TestCase;

public class CalculatorTest2 extends TestCase {

private Calculator calc = new Calculator();

public void testAdd() {
calc.add(
0,4);
int result = 4;
// 通过 Assert 对 function 功能进行测试
Assert.assertEquals(result, calc.getResult());
}

}
 

JUnit4的实现

package com.rigel.ut;

import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {

private Calculator calc = new Calculator();

@Test
public void testAdd() {
calc.add(
0,4);
int result = 4;
// 通过 Assert 对 function 功能进行测试
Assert.assertEquals(result, calc.getResult());
}
}

总 结一下,在JUnit3中,编写的测试类强制要求继承”TestCase“类,而且测试方法必须以”test*“开头;而在JUnit4中,通过元注解代 替对测试方法的一些强制约定,这样可以使得代码更加简化,可懂度也要好很多。当然,由于这个例子比较简单,两者之间很多其他不同之处都没有体现出来,比如 在 JUnit3中的Fixture方法硬性规定为”setUp“ & "tearDown",而在JUnit4中,则只要用”@Before“ & ”@After“元注解来标识方法就可以,至于方法名,则不作限制。

可参考:http://blog.sina.com.cn/s/blog_4ce9e82e0100bh1t.html

2. JUnit4中一些常用的元注解

@Test

这个注解我们在上例之中已经见过,主要是用来标注测试方法;

@Test(timeout = *** )

该元数据传入了一个时间(毫秒)给测试方法,如果测试方法在制定的时间之内没有运行完,则测试也失败;
@Test(expected=*.class)
在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,通过@Test元数据中的expected属性。expected属性的值是一个异常的类型。
@Ignore
该 元数据标记的测试方法在测试中会被忽略。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而 在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方 法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。
下面我们通过实例来分析这些注解的使用,首先我们扩充下之前写的那个Calculator类,代码如下所示:
package com.rigel.ut;

/**
* 一个计算器功能类
*
*
*/
public class Calculator {

private int result; /* 保存计算的结果 */

/**
* 实现加法功能
* 为了测试 @Test 注解
*
*/
public void add(int a, int b) {
result
= a + b;
}

/**
* 实现减法功能
* 为了函数测试失败的情况,这个函数功能故意写错。
*
*/
public void substract(int a, int b) {
result
= a - b;
}

/**
* 实现乘法功能,该方法暂未实现
* 为了方便测试 @Ignore 注解
*
*/
public void multiply(int a, int b) {
// do nothing.
}

/**
* 实现除法功能
* 为了方便测试 @Test(expected=*.class)注解,即异常情况
*
*/
public void devide(int a, int b) {
result
= a / b;
}

/**
* 实现平方的功能
* 方法故意写错,主要为了测试超时的情况,即测试@Test(timeout = ***)
*
*/
public void square(int n) {
// 死循环
for(;;);
}

/**
* 清除计算结果
*
*/
public void clear() {
result
= 0;
}

public void setResult(int result) {
this.result = result;
}
public int getResult() {
return this.result;
}

}
针对该Calculator的各功能方法分别测试,TestCase实现如下:
package com.rigel.ut;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

public class CalculatorTest {

private Calculator calc = new Calculator();

@Test
public void testAdd() {
calc.add(
0,4);
int result = 4;
Assert.assertEquals(result, calc.getResult());
}

@Test
public void testSubstract() {
calc.clear();
calc.substract(
0,5);
int result = -5;
Assert.assertEquals(result, calc.getResult());
}

@Ignore
public void testMultiply() {
// multiply 功能未实现,该测试方法暂不执行
}

@Test(expected
= ArithmeticException.class)
public void testDevide() {
calc.devide(
5,0);
}

@Test(timeout
= 5000)
public void testSquare() {
calc.square(
5);
}
}
这些测试方法分别针对测试成功、失败、期望出现异常及超时的情况进行分析,最后Testcase Run 的结果如下:

其中,在 ”Failure Trace“详细解析了失败及Error的原因,如上图,Failure提示的信息为:函数期望值为-1,而测试指定的结果为-5;另外也可以看到@Ignore注解的测试方法“testMultiply”被运行器忽略了,并未执行;而@Test(timeout="***")注解的方法“testSquare”则由于超时抛出Error;

接下来介绍的元注解对应Fixture方法。所谓Fixture是指在执行一个或者多个测试方法时需要的一系列公共资源或者数据。说的简单点就是“在某些阶段必然被调用的代码”。JUnit4中对应修饰Fixture方法的元注解如下:
@Before
@After
也称为方法级别的Fixture。其在每一个测试方法执行之前,JUnit 会保证带有@Before注解的方法已经提前初始化测试环境,而当此测试方法执行完毕之后,JUnit 又会调用带有@After注解的方法注销测境。这样便可以保证各个独立的测试之间互不干扰,以免其它测试代码修改测试环境或者测试数据影响到其它测试代码 的准确性。其流程如下所示:
@BeforeClass
@AfterClass

也称为类级别的Fixture。其在所有的测试方法执行之前,JUnit 会保证带有@BeforeClass注解的方法已经提前初始化测试环境,而当所有的测试方法执行完毕之后,JUnit 又会调用带有@AfterClass注解的方法注销测试环境。这主要是针对TestCase中,很多测试方法不需要一次次的执行相同的初始化及注销方法,以提高测试的效率;其流程如下图所示:

接下来测试 Fixture 方法对应的元注解,我们从新写一个TestCase,其内容如下:

package com.rigel.ut;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class FixtureTest {

@Before
public void before() {
System.out.println(
"before method running");
}

@After
public void after() {
System.out.println(
"after method running");
}

@BeforeClass
public static void beforeClass() {
System.out.println(
"before all method running");
}
@AfterClass
public static void afterClass() {
System.out.println(
"after all method running");
}

@Test
public void test1() {
System.out.println(
"test1 method");
}

@Test
public void test2() {
System.out.println(
"test2 method");
}

}

其中,@BeforeClass 和 @AfterClass 对应的是类级别的Fixture,所以方法必须申明为static,TestCase的运行结果如下所示:

从图中可以看出:

@BeforeClass 对应的方法最先执行,且只执行了一次;

@AfterClass 对应的方法最后执行,也只执行了一次;

@Before 对应的方法执行了两次,其在每个@Test标注的方法之前执行,即在每个测试方法之前执行;

@After 对应的方法执行了两次,在每个测试方法执行完之后执行;

总 结一下,本章节首先简要的分析了JUnit4与JUnit3的不同之处,然后详细讲解了JUnit4中常用的元注解的使用。在测试用例中,所有的测试方法 都是通过Assert.assertEquals(...)方法来判定,当然,Assert还有很多其他方法可以使用,其常用的方法如下,具体大家可参考 相应的文档。

本章节到此结束,下一章节将介绍JUnit4的一些高级特性。

原文地址:https://www.cnblogs.com/shine_cn/p/2060917.html