测试是项目开发中很重要的一环。实际上,建议的项目前期编写过程是:构思-> 编写单元测试代码-> 编写接口->编写实现类-> 测试实现类->编写主类...。JUnit是一个使用广泛的、用于编写和运行可重复的测试的Java测试框架。这里不多介绍背景,直接说用法了。

1.JUnit测试用例的创建

首先,在pom.xml(Maven)中添加依赖:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

然后,在src/test/java下的包中新建>JUnit测试用例,在下图所示界面中选择“新建JUnit4测试”(1),填写类名(2)和要测试的类(3),选择要创建的方法存根(4),点击下一步:

这里介绍一下可选的方法存根(4):

  • setUpBeforClass():注解@BeforeClass,在运行测试类的最开始运行一次,用作测试准备(读取文件、链接数据库等)。
  • tearDownAfterClass():注解@AfterClass,在运行测试类的最后运行一次,用作测试清理(释放资源)。
  • setUp():注解@Befor,在运行每个要测试方法前运行,有多少个要测试的方法就运行多少次,用作测试方法准备。
  • tearDown():注解@After,在运行每个要测试方法后运行,有多少个要测试的方法就运行多少次,用作测试方法清理。

最后,选择要测试的方法,点击完成:

在生成的测试类中,会对每个选中的方法生成一个测试方法(testXxx)。如果选中了“创建终态方法存根”,则生成的测试方法都带有final修饰符;如果选中了“为生成的测试方法创建任务”,则生成的测试方法中都会出现//TODO标识。

2.测试类的编写

(1)JUnit4中的注解

  • @BeforeClass:该方法在所有测试方法运行之前,运行一次。方法必须是public static void。
  • @AfterClass:该方法在所有测试方法运行完毕后,运行一次。方法必须是public static void。
  • @Before:该方法在每个@Test运行之前都要运行。方法必须是public void。
  • @After:该方法在每个@Test运行之后都要运行。方法必须是public void。
  • @Test:表示该方法是测试方法。方法必须是public void。@Test可以有两个参数:expected,timeout,分别对应异常测试和超时测试。
  • @Ignore:对测试类或@Test测试方法使用,表示暂时忽略该测试。JUnit执行结果会报告忽略数量。

通过步骤1生成的测试类,会在setUpBeforeClass、tearDownAfterClass、setUp、tearDown、testXxx方法前自动添加相应注解。

(2)Assert类

Assert类是JUnit中提供的一个工具类,这个类中有大量的静态方法进行断言的处理。在各测试方法中,在调用要测试的方法后,通过Assert类中的方法判断运行结果是否符合预期。

一般为了方便使用Assert类中的静态方法,在测试类中对Assert类中的方法进行静态导入:

import static org.junit.Assert.*;

这里简单介绍几种Assert类中的常见方法(细节详见Assert(JUnit API)):

  • assertArrayEquals((错误信息,)预期结果数组,测试结果数组):断言测试结果数组与预期结果数组相等。如果不相等,抛出AssertionError,表示测试未通过。如果存在信息参数,则抛出带指定信息的AssertionError。
  • assertEquals((错误信息,)预期结果,测试结果):断言测试结果==预期结果。如果不相等,处理方式同上。
  • assertNotEquals((错误信息,)不期望的结果,测试结果):断言测试结果不等于不期望的结果。如果相等,处理方式同上。
  • assertNull((错误信息,)Object):断言对象为空。如果不为空,处理方式同上。
  • assertNotNull((错误信息,)Object):断言对象不为空。如果为空,处理方式同上。
  • assertSame((错误信息,)期望Object,测试Object):断言测试Object和期望Object引用了同一对象。如果引用了不同对象,处理方式同上。
  • assertNotSame((错误信息,)不期望的Object,测试Object):断言测试Object引用的不是不期望的Object。如果引用同一对象,处理方式同上。
  • assertTrue((错误信息,)boolean):断言判定条件(boolean)为true。如果为false,处理方式同上。
  • assertFalse((错误信息,)boolean):断言判定条件(boolean)为false。如果为true,处理方式同上。
  • assertThat((错误信息,)结果参数T,Matcher<? super T>):断言结果参数满足Matcher的条件。如果不满足,抛出带有Matcher和结果信息的AssertionError。如果存在信息参数,则抛出的AssertionError还带有错误信息。
  • fail((识别信息)):使测试不通过。如果存在信息参数,则为测试不通过加上识别信息。

当比较对象为double或float时,应加上对应类型的delta参数,即:判定比较对象相等时的最大误差。

(3)测试方法的编写

对于每个测试方法,一般都是先调用要测试的方法,然后通过Assert中的方法,判断测试结果是否符合预期。

对于每个要测试的方法,可以有3个测试方法:运行结果测试、异常测试、性能测试。三者的功能分别是测试指定方法运行结果是否符合预期、有问题时是否能正确抛出异常、能否在限定时间内完成运行,参数分别是@Test、@Test(expected=XxxException.class)、@Test(timeout=xxx)。可以根据实际需求,选择编写其中的1~3个测试方法。

注意,每个test方法中最好只测试被测类中的一种方法,尽量不要在一个test方法中调用两个以上的被测方法。

节选示例:测试向数据库添加学生信息的addStu方法和通过专业学号查询数据的query...方法。

被测试方法:

    public StudentDAOImpl() {
// TODO 自动生成的构造函数存根
apc = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = (JdbcTemplate) apc.getBean("jdbcTemplate");
} public boolean addStu(Student stu) {
// TODO 自动生成的方法存根
String name = stu.getName(), major = stu.getMajor();
int jnshuId = stu.getJnshuId();
if (name==null || major==null || jnshuId==0) {
throw new RuntimeException("姓名、专业、学号不能为空!");
}
String sql = "INSERT INTO students (name,qq,major,entrytime,gra_school,id_jnshu"
+ ",daily_url,desire,bro_jnshu,knowfrom) VALUES (?,?,?,?,?,?,?,?,?,?)";
int line = jdbcTemplate.update(sql,new Object[] {
name,stu.getQq(),major,stu.getEntryTime(),
stu.getSchool(),jnshuId,stu.getDailyUrl(),stu.getDesire(),
stu.getJnshuBro(),stu.getKnowFrom()});
return line>0?true:false;
} public Student queryStuByJnshu(String major, int jnshuId) {
// TODO 自动生成的方法存根
String sql = "SELECT id,create_at,update_at,name,qq,major,entrytime,gra_school,id_jnshu" +
",daily_url,desire,bro_jnshu,knowfrom FROM students WHERE id_jnshu=? and major=?";
Student stu = null;
try {
stu = jdbcTemplate.queryForObject(sql, new QueryStuRowMapper(),new Object[]{jnshuId,major});
} catch (EmptyResultDataAccessException e) {
// TODO 此处可做更复杂的提示动作,比如抛出异常、记录到本地文件、显示到GUI等。
System.out.println("该学生不存在!");
}
return stu;
}

其中,QueryStuRowMapper代码如下:

package cn.cage.student;

import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper; public class QueryStuRowMapper implements RowMapper<Student> {
/**
* 直接使用此类建立的对象时,sql语句应查询Student的所有属性。*/
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
// TODO 自动生成的方法存根
Student stu = new Student(rs.getString("name"), rs.getString("major"), rs.getInt("id_jnshu"));
stu.setId(rs.getLong("id"));
stu.setCreateTime(rs.getLong("create_at"));
stu.setUpdateTime(rs.getLong("update_at"));
stu.setQq(rs.getString("qq"));
// TODO 此处根据测试结果(时间格式)看是否需要修改
stu.setEntryTime(rs.getDate("entrytime").toString());
stu.setSchool(rs.getString("gra_school"));
stu.setDailyUrl(rs.getString("daily_url"));
stu.setDesire(rs.getString("desire"));
stu.setJnshuBro(rs.getString("bro_jnshu"));
stu.setKnowFrom(rs.getString("knowfrom"));
return stu;
}
}

测试方法:

    @BeforeClass
public static void setUpBeforeClass() throws Exception {
stuDao = new StudentDAOImpl();
} @AfterClass
public static void tearDownAfterClass() throws Exception {
stuDao = null;
} @Test
public void testAddStu() {
Student stu = new Student("王五", "Java后端工程师", 1470);
assertTrue("插入失败!",stuDao.addStu(stu));
} @Test
public void testQueryStuByJnshu() {
Student stu = new Student("王五", "Java后端工程师", 1470);
Student actual = stuDao.queryStuByJnshu("Java后端工程师", 1470);
assertEquals("插入错误,或查询方法(byJnshu)有问题!",stu, actual);
}

3.运行测试

编写完测试类和被测试类后,在测试类上右键>运行方式>JUnit测试即可。

注意:运行测试的顺序并非是按照函数的先后顺序!如果要修改运行测试的顺序,可以在class上加注解:@FixMethodOrder(*)。可以选择的参数有:

  • MethodSorters.DEFAULT:默认顺序,不可预测但固定的顺序(每次顺序都相同)。
  • MethodSorters.JVM:测试方法执行顺序为JVM返回的顺序,不固定的顺序(每次顺序可能不同)
  • MethodSorters.NAME_ASCENDING:按测试方法名(字典顺序)升序执行。(如果是自定义顺序,推荐这种)

虽然可以改变测试顺序,但一个好的测试类不应该依赖于测试顺序!

示例测试结果:

插入成功,但查询结果与插入值不同。

找到原因,是Student类中没有equals函数,所以assertEquals比较的是查询结果与插入值是否引用了同一个对象。修改后测试通过。

JUnit4在Eclipse中的使用的更多相关文章

  1. [转]在Eclipse中使用JUnit4进行单元测试(初级篇)

    首先,我们来一个傻瓜式速成教程,不要问为什么,Follow Me,先来体验一下单元测试的快感! 首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除 ...

  2. 在Eclipse中使用JUnit4进行单元测试(初级篇)

    首先,我们来一个傻瓜式速成教程,不要问为什么,Follow Me,先来体验一下单元测试的快感! 首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除 ...

  3. 在Eclipse中使用JUnit4进行单元测试

    在Eclipse中使用JUnit4进行单元测试(初级篇) 在Eclipse中使用JUnit4进行单元测试(中级篇) 在Eclipse中使用JUnit4进行单元测试(高级篇)

  4. 【Java】在Eclipse中使用JUnit4进行单元测试(初级篇)

    本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能 ...

  5. 在Eclipse中使用JUnit4进行单元測试(0基础篇)

    本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,须要写成千上万个方法或函数,这些函数的功能可能 ...

  6. 在Eclipse中使用JUnit4进行单元测试(图文教程一)

    在Eclipse中使用JUnit4进行单元测试 单元测试,JUnit4. 这两个有什么关系呢?这就好比(草)单元测试和(割草机).用这个JUnit4工具去辅助我们进行测试.其实不理解这个也没关系,听多 ...

  7. 在eclipse中使用JUnit4,以及使用JUnit4进行单元测试的技巧

    一 在eclipse中使用JUnit4 首先在工程上右键,选择属性,找到Java Builder Path,添加JUnit4的lib,如下图:   在要测试的类上右键新建 Junit test cas ...

  8. 【转】在Eclipse中使用JUnit4进行单元测试(初级篇)

    http://www.builder.com.cn/2007/0901/482336.shtml 首先,我们来一个傻瓜式速成教程,不要问为什么,Follow Me,先来体验一下单元测试的快感! 首先新 ...

  9. (转)Eclipse中junit框架的使用——单元测试

    [转]junit浅学笔记一 JUnit是一个回归测试框架(regression testing framework).Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How ...

随机推荐

  1. 【Android Developers Training】 68. 序言:添加动画

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. 【Android Developers Training】 66. 添加动画

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 一个简单的python选课系统

    下面介绍一下自己写的python程序,主要是的知识点为sys.os.json.pickle的模块应用,python程序包的的使用,以及关于类的使用. 下面是我的程序目录: bin是存放一些执行文件co ...

  4. react系列从零开始-react介绍

    react算是目前最火的js MVC框架了,写一个react系列的博客,顺便回忆一下react的基础知识,新入门前端的小白,可以持续关注,我会从零开始教大家用react开发一个完整的项目,也会涉及到w ...

  5. linux命令行解刨

    linux命令需要在命令行界面上操作(windows的cmd也是一个命令行界面).只有在了解命令行界面含义才能知道我们输入这些命令意义是什么,为什么要输入这些命令. 首先我们要知道怎么找出linux输 ...

  6. 把对象列表转化成json数据格式

    package JsonTest; import java.util.ArrayList; import java.util.List; public class test { public stat ...

  7. Vijos 1007 绕钉子的长绳子

    背景 平面上有N个圆柱形的大钉子,半径都为R,所有钉子组成一个凸多边形. 现在你要用一条绳子把这些钉子围起来,绳子直径忽略不计. 描述 求出绳子的长度 格式 输入格式 第1行两个数:整数N(1< ...

  8. 浅谈关于特征选择算法与Relief的实现

    一. 背景 1) 问题 在机器学习的实际应用中,特征数量可能较多,其中可能存在不相关的特征,特征之间也可能存在相关性,容易导致如下的后果: 1.     特征个数越多,分析特征.训练模型所需的时间就越 ...

  9. Java WebService学习资料

    最近用到了WebService,以前没用过,想要好好学习一下.感觉网上资料比较少,而且很杂,找了很久,觉得下面的两个文章解释的比较清楚,分享一下: WebService概念.原理:http://mp. ...

  10. javascript精度问题与调整

    一个经典的问题: 0.1+0.2==0.3 答案是:false 因为:0.1+0.2=0.30000000000000004 第一次看到这个结果就是无比惊讶,下巴碰到地上,得深入了解下问题出在哪里,该 ...