junit4 单元测试

最近在做单元测试,于是,从网上找到一些资料并整理如下:

JUnit4 基本上是一个新框架,而不是旧框架的升级版本。其主要目标便是利用Java 5的Annotation特性简化测试用例的编写。

要求:JDK 5.0或以上版本。


Java注解((Annotation)的使用方法是@注解名 ,能通过简单的词语来实现一些功能。在junit中常用的注解有@Test、@Ignore、@BeforeClass、@AfterClass、@Before、@After、@Runwith、@Parameters

以下是相关的介绍和使用说明:

.@Test

在junit3中,是通过对测试类和测试方法的命名来确定是否是测试,且所有的测试类必须继承junit的测试基类。在junit4中,定义一个 测试方法变得简单很多,只需要在方法前加上@Test就行了。

注意:测试方法必须是public void,即公共、无返回数据。可以抛出异常。

.@Ignore

扫描二维码关注公众号,回复: 852905 查看本文章

有时候我们想暂时不运行某些测试方法\测试类,可以在方法前加上这个注解。在运行结果中,junit会统计忽略的用例数,来提醒你。但是不建议经常这么做,因为这样的坏处时,容易忘记去更新这些测试方法,导致代码不够干净,用例遗漏。

.@BeforeClass

当我们运行几个有关联的用例时,可能会在数据准备或其它前期准备中执行一些相同的命令,这个时候为了让代码更清晰,更少冗余,可以将公用的部分提取出来,放在一个方法里,并为这个方法注解@BeforeClass。意思是在测试类里所有用例运行之前,运行一次这个方法。例如创建数据库连接、读取文件等。

注意:方法名可以任意,但必须是public static void,即公开、静态、无返回。这个方法只会运行一次。

.@AfterClass

跟@BeforeClass对应,在测试类里所有用例运行之后,运行一次。用于处理一些测试后续工作,例如清理数据,恢复现场。

注意:同样必须是public static void,即公开、静态、无返回。这个方法只会运行一次。

.@Before

与@BeforeClass的区别在于,@Before不止运行一次,它会在每个用例运行之前都运行一次。主要用于一些独立于用例之间的准备工作。比如两个用例都需要读取数据库里的用户A信息,但第一个用例会删除这个用户A,而第二个用例需要修改用户A。那么可以用@BeforeClass创建数据库连接。用@Before来插入一条用户A信息。

注意:必须是public void,不能为static。不止运行一次,根据用例数而定。

.@After

与@Before对应。

.@Runwith

首先要分清几个概念:测试方法、测试类、测试集、测试运行器。

其中测试方法就是用@Test注解的一些函数。测试类是包含一个或多个测试方法的一个**Test.java文件,测试集是一个suite,可能包含多个测试类。测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法。

而@Runwith就是放在测试类名之前,用来确定这个类怎么运行的。也可以不标注,会使用默认运行器。

常见的运行器有:

1. @RunWith(Parameterized.class) 参数化运行器,配合@Parameters使用junit的参数化功能

2.@RunWith(Suite.class)
@SuiteClasses({ATest.class,BTest.class,CTest.class})

测试集运行器配合使用测试集功能

3.@RunWith(JUnit4.class)

junit4的默认运行器

4.@RunWith(JUnit38ClassRunner.class)

用于兼容junit3.8的运行器

5.一些其它运行器具备更多功能。例如@RunWith(SpringJUnit4ClassRunner.class)集成了spring的一些功能

.@Parameters

用于使用参数化功能。


其他:

1)对测试异常,JUnit 4可以用expected=Exception.class来期待一个预期的异常,而不必手动编写。参数 expected 代表测试方

法期望抛出指定的异常,如果运行测试并没有抛出这个异常,则 JUnit4 会认为这个测试没有通过。如:

publicint div(inta,int b){

return a / b;

}

可能会抛出除数为0的异常,可以这样来编写:

@Test(expected=ArithmeticException.class)

public void testDiv(){

cal.div(5, 0);

}

@Test(expected = NullPointerException.class)

public void unsupportedDBCheck() {

throw new NullPointerException();

}

2)设置最长执行时间

参数timeout,指定被测试方法被允许运行的最长时间应该是多少,如果测试方法运行时间超过了指定的毫秒数,则JUnit认为

测试失败。

@Test(timeout=1)

public void testMinus(){

assertEquals(cal.minus(2, 1), 1);

}

3)Ignore 用于暂时忽略某个测试方法,因为有时候由于测试环境受限,并不能保证每一个测试方法都能正确运行。

@Ignore("db is down")

@Test(expected=UnsupportedDBVersionException.class)

public void unsupportedDBCheck(){

}

3)类级别的Fixture设置方法

注解@BeforeClass修饰用于初始化Fixture的方法。注解@AfterClass 修饰用于注销Fixture的方法。由于这二个方法在运行其间仅执行一次,因此它们只能标记为静态方法(使用 public static void 修饰,而且不能带有任何参数),其实在所有的测试方法中

共享的资源也必须是静态引用。如:

@BeforeClass

public static void dbInit(){//类级别Fixture初始化方法

}

@AfterClass

public static void dbClose(){//类级别Fixture注销方法

}

类级别的Fixture方法,仅会在测试类中所有测试方法执行之前执行初始化,并在全部测试方法测试完毕之后执行注销方法。

4)测试运行机

JUnit 中所有的测试方法都是由它负责执行的。JUnit 为单元测试提供了默认的测试运行器,但 JUnit 并没有限制您必须使用默认的2


运行器。相反,您不仅可以定制自己的运行器(所有的运行器都继承自 org.junit.runner.Runner),而且还可以为每一个测试类指

定使用某个具体的运行器。指定方法也很简单,使用注解 org.junit.runner.RunWith 在测试类上显式的声明要使用的运行器即可:

@RunWith(CustomTestRunner.class)

public class TestWordDealUtil{

}

5)测试套件

JUnit 提供了一种批量运行测试类的方法,叫做测试套件。这样,每次需要验证系统功能正确性时,只执行一个或几个测试套件便可

以了。测试套件的写法非常简单,需要遵循以下规则:

(1)创建一个空类作为测试套件的入口。

(2)使用注解 org.junit.runner.RunWith 和 org.junit.runners.Suite.SuiteClasses 修饰这个空类。

(3)将 org.junit.runners.Suite 作为参数传入注解 RunWith,以提示 JUnit 为此类使用套件运行器执行。

(4)将需要放入此测试套件的测试类组成数组作为注解 SuiteClasses 的参数。

(5)保证这个空类使用 public 修饰,而且存在公开的不带有任何参数的构造函数。

importorg.junit.runner.RunWith;

importorg.junit.runners.Suite;


@RunWith(Suite.class)

@Suite.SuiteClasses({TestWordDealUtil.class,xxx.class})

public class RunAllUtilTestsSuite {

}

测试套件中不仅可以包含基本的测试类,而且可以包含其它的测试套件,这样可以很方便的分层管理不同模块的单元测试代码。但

是,您一定要保证 测试套件之间没有循环包含关系。

6)参数化测试

(1)为准备使用参数化测试的测试类指定特殊的运行器 org.junit.runners.Parameterized。

(2)为测试类声明几个变量,分别用于存放期望值和测试所用数据。

(3)为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters 修饰的,返回值为 java.util.Collection 的公共静

态方法,并在此方法中初始化所有需要测试的参数对。

(4)为测试类声明一个带有参数的公共构造函数,并在其中为第二个环节中声明的几个变量赋值。

(5)编写测试方法,使用定义的变量作为参数进行测试。

@RunWith(Parameterized.class)

public class TestWordDealUtilWithParam {

private String expected;

private String target;


@Parameters

public static Collection words(){

returnArrays.asList(new Object[][]{

{"employee_info", "employeeInfo"},        //测试一般的处理情况

{null, null},                            //测试 null 时的处理情况

{"", ""},                                //测试空字符串时的处理情况

{"employee_info", "EmployeeInfo"},        //测试当首字母大写时的情况

{"employee_info_a", "employeeInfoA"},    //测试当尾字母为大写时的情况

{"employee_a_info", "employeeAInfo"}    //测试多个相连字母大写时的情况

});

}


publicTestWordDealUtilWithParam(String expected , String target){

this.expected = expected;

this.target = target;

}

//测试将 Java 对象名称到数据库名称的转换

@Test

public void wordFormat4DB(){

assertEquals(expected, WordDealUtil.wordFormat4DB(target));

}

猜你喜欢

转载自change-jeans.iteye.com/blog/2200824