文档章节

JUnit4单元测试、JUnit4使用详解、assertThat用法

谢思华
 谢思华
发布于 2013/11/13 21:29
字数 2872
阅读 3010
收藏 2

一.JUnit基本介绍

1、简介       

         JUnit是一个开放源码的、Java语言的单元测试框架,用于测试期望结果的断言(Assertion);由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。多数Java的开发环境都已经集成了JUnit作为单元测试的工具,如Eclipse。

        测试一般分为:单元测试、集成测试(主要看一块代码加进去后,系统会不会有问题)、验收测试和压力测试。单元测试的最基本的一个功能是能进行自动化测试。单元测试都是通过断言的方式来确定结果是否正确,即是用Assert。

2、优点

        junit是在极限编程重构(refactor)中被极力推荐使用的工具,因为在实现自动单元测试的情况下可以大大的提高开发的效率。

        极限编程:要求在编写代码之前先写测试,这样可以强制你在写代码之前好好的思考代码(方法)的功能和逻辑,否则编写的代码很不稳定,那么你需要同时维护测试代码和实际代码,这个工作量就会大大增加。因此在极限编程中,基本过程是这样的:构思-> 编写测试代码-> 编写代码-> 测试,而且编写测试和编写代码都是增量式的,写一点测一点,在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。

        重构:其好处和极限编程中是类似的,因为重构也是要求改一点测一点,减少回归错误造成的时间消耗。

3、Junit3与Junit4

        在junit3中,如果某个类是测试类,必须将其继承类TestCase,如果某个方法是测试方法,必须让这个方法以testXX开头,如果希望指定某个测试方法运行之前运行某个初始化方法,这个方法的名称必须是setUp,如果希望在某个测试方法运行之后运行某个释放资源的方法,这个方法的名称必须是tearDown。
        在junit4中,一个POJO类就是一个测试类,测试方法通过@Test来标识,初始化方法通过@Before来标识,释放资源的方法通过@After来标识,但是为了让junit4的测试类在junit3中也可以使用,习惯于把初始化方法命名为setUp,释放资源的方法命名为tearDown。Test中的测试方法一般以Test来开始。其中标识为Before注解的方法,每次运行测试类,都会执行标识为@After与@Before的方法。

 

二.JUnit单元测试

        由于JUnit4引用了很多Annotation注解以后,用JUnit进行单元测试比较方便,主要关键点在于:注解,断言的使用;

        以下为测试的示例:

待测试类

package com.test;

/**
 * 计算类
 * @author helen.
 * @Time 2016年5月13日
 * @Version 1.0
 */
public class Calculator {
	
	public int add(int a, int b) {  
		System.out.println("=======正在执行加法");
        return a + b;  
    }  
  
    public int minus(int a, int b) {  
    	System.out.println("=======正在执行减法");
        return a - b;  
    }  
  
    public int square(int n) {  
    	System.out.println("=======正在执行平方计算");
        return n * n;  
    }  
      
    //Bug : 死循环  
    public void squareRoot(int n) {  
    	System.out.println("=======正在执行死循环的方法");
        for(; ;)  
            ;  
    }  
      
    public int multiply(int a, int b) {  
    	System.out.println("=======正在执行乘法");
        return a * b;  
    }  
  
    public int divide(int a, int b) throws Exception { 
    	System.out.println("=======正在执行除法");
        if (0 == b) {  
            throw new Exception("除数不能为零");  
        }  
        return a / b;  
    }
    
}

单元测试类

package com.test;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import static org.hamcrest.Matchers.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;

/**
 * 计算类单元测试
 * @author helen.
 * @Time 2016年5月13日
 * @Version 1.0
 */
public class CalculatorTest {

	private Calculator cal = new Calculator();  
	  
	/**
	 * 注意
	 * 必须为静态方法static...因为方法将在类被装载的时候就被调用(那时候还没创建实例) 
	 * 
	 * @author helen, 2016年5月13日.
	 */
    @BeforeClass 
    public static void before()  
    {  
        System.out.println("global");  
    }  
  
    @AfterClass  
    public static void after() {  
        System.out.println("global destroy");  
    }  
  
    @Before  
    public void setUp() throws Exception {  
        System.out.println("one test begin");  
    }  
  
    @After  
    public void tearDown() throws Exception {  
        System.out.println("one test end");  
    }  
  
    @Test  
    @Ignore  
    public void testAdd() {  
        int result = cal.add(1, 2);  
        Assert.assertEquals(30, result);  
    }  
  
    @Test  
    public void testMinus() {  
        int result = cal.minus(5, 2);  
        Assert.assertThat(result, greaterThan(2));
    }

    @Test  
    public void testMultiply() {  
        int result = cal.multiply(4, 2);  
        Assert.assertEquals(8, result);  
    }  
  
    @Test(timeout = 1000) // 单位为毫秒  
    public void testSquareRoot() {  
        cal.squareRoot(4);  
    }  
  
    @Test(expected = Exception.class)  
    public void testDivide() throws Exception {  
        cal.divide(4, 0);  
    } 

}

    运行测试用:在Eclipse里Run As -> JUnit Test,运行测试类,Eclipse的JUnit的View显示以及控制台的输出如下截图: 

        可以看到,CalculatorTest类中总共有5个测试用例,ignore了一个,3个测试用例通过,testSquareRoot测试不通过(因为超时),所以整个的测试结果飘红了。

 

三.JUnit使用详解

1、注解说明

@Test:
表明该方法是一个测试方法
 
@BeforeClass 和 @AfterClass:
测试用例初始化时执行 @BeforeClass方法,当所有测试执行完毕之后,执行@AfterClass进行收尾工作。标注、@BeforeClass 和 @AfterClass的方法必须是static的,因为方法将在类被装载的时候就被调用,那时候还没创建测试对象实例。
 
@Before: 
使用了该元数据的方法在每个测试方法执行之前都要执行一次。
@After: 
使用了该元数据的方法在每个测试方法执行之后要执行一次。
 
@Test(expected=*.class) :
通过@Test元数据中的expected属性验证是否抛出期望的异常,expected属性的值是一个异常的类型,如果抛出了期望的异常,则测试通过,否则不通过。
 
@Test(timeout=xxx):
该元数据传入了一个时间(毫秒)给测试方法,如果测试方法在制定的时间之内没有运行完,则测试也失败。
 
@Ignore: 
该元数据标记的测试方法在测试中会被忽略。同时可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。比如:@lgnore("该方法还没有实现"),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

 

2、常用断言

        在test方法内除了使用Assert的assertEquals()方法外,还能使用assertFalse()、assertTrue()、assertNull()、assertNotNull()、assertSame()、assertNotSame()等断言函数。而且如果使用的是Junit4,结合Hamcrest,使用
assertThat([value], [matcher statement])方法可以实现更灵活的断言判断(前提是引入hamcrest的jar包)。

        如果不需要用到assertThat,则只需要用Eclipse自带的junit4工具即可;如果需要用到assertThat,则最好不要Eclipse自带的工具,重新通过maven方式引入jar

		<dependency>
		    <groupId>junit</groupId>
		    <artifactId>junit</artifactId>
		    <version>4.11</version>
		</dependency>				
		<dependency>
		    <groupId>org.hamcrest</groupId>
		    <artifactId>hamcrest-all</artifactId>
		    <version>1.3</version>
		</dependency>

 

四.assertThat用法(断言使用)

Hamcrest框架和assertThat:

1.JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活;
2.使用全新的断言语法:assertThat,结合Hamcest提供的匹配符,只用这一个方法,就可以实现所有的测试;
3.assertThat语法如下:
     assertThat(T actual, Matcher<T> matcher);
     assertThat(String reason, T actual, Matcher<T> matcher);
     其中actual为需要测试的变量,matcher为使用Hamcrest的匹配符来表达变量actual期望值的声明;
4.注意事项:
     a.必须导入JUnit4.4之后的版本才能使用assertThat方法;
     b.不需要继承TestCase类,但是需要测试方法前必须加“@Test”。

 

常用:

// is匹配符表明如果前面待测的object等于后面给出的object,则测试通过 
assertThat( testedObj, is( object) ); 
 
// containsString匹配符表明如果测试的字符串包含指定的子字符串则测试通过
 assertThat( testedString, containsString( "developerWorks" ) );
 
// greaterThan匹配符表明如果所测试的数值testedNumber大于16.0则测试通过
 assertThat( testedNumber, greaterThan(16.0) ); 
 
// closeTo匹配符表明如果所测试的浮点型数testedDouble在20.0±0.5范围之内则测试通过 
assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
 
//hasItem匹配符表明被测的迭代对象含有元素element项则测试通过assertThat(iterableObject, hasItem (element));

 

一般匹配符:

1、assertThat( testedNumber, allOf( greaterThan(8), lessThan(16) ) );
注释: allOf匹配符表明如果接下来的所有条件必须都成立测试才通过,相当于“与”(&&)
2、assertThat( testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
注释:anyOf匹配符表明如果接下来的所有条件只要有一个成立则测试通过,相当于“或”(||)
3、assertThat( testedNumber, anything() );
注释:anything匹配符表明无论什么条件,永远为true
4、assertThat( testedString, is( "developerWorks" ) );
注释: is匹配符表明如果前面待测的object等于后面给出的object,则测试通过
5、assertThat( testedString, not( "developerWorks" ) );
注释:not匹配符和is匹配符正好相反,表明如果前面待测的object不等于后面给出的object,则测试通过

 

字符串相关匹配符

1、assertThat( testedString, containsString( "developerWorks" ) );
注释:containsString匹配符表明如果测试的字符串testedString包含子字符串"developerWorks"则测试通过
2、assertThat( testedString, endsWith( "developerWorks" ) ); 
注释:endsWith匹配符表明如果测试的字符串testedString以子字符串"developerWorks"结尾则测试通过
3、assertThat( testedString, startsWith( "developerWorks" ) ); 
注释:startsWith匹配符表明如果测试的字符串testedString以子字符串"developerWorks"开始则测试通过
4、assertThat( testedValue, equalTo( expectedValue ) ); 
注释: equalTo匹配符表明如果测试的testedValue等于expectedValue则测试通过,equalTo可以测试数值之间,字
符串之间和对象之间是否相等,相当于Object的equals方法
5、assertThat( testedString, equalToIgnoringCase( "developerWorks" ) ); 
注释:equalToIgnoringCase匹配符表明如果测试的字符串testedString在忽略大小写的情况下等于"developerWorks"则测试通过
6、assertThat( testedString, equalToIgnoringWhiteSpace( "developerWorks" ) );
注释:equalToIgnoringWhiteSpace匹配符表明如果测试的字符串testedString在忽略头尾的任意个空格的情况下等
于"developerWorks"则测试通过,注意:字符串中的空格不能被忽略

 

数值相关匹配符

1、assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
注释:closeTo匹配符表明如果所测试的浮点型数testedDouble在20.0±0.5范围之内则测试通过
2、assertThat( testedNumber, greaterThan(16.0) );
注释:greaterThan匹配符表明如果所测试的数值testedNumber大于16.0则测试通过
3、assertThat( testedNumber, lessThan (16.0) );
注释:lessThan匹配符表明如果所测试的数值testedNumber小于16.0则测试通过
4、assertThat( testedNumber, greaterThanOrEqualTo (16.0) );
注释: greaterThanOrEqualTo匹配符表明如果所测试的数值testedNumber大于等于16.0则测试通过
5、assertThat( testedNumber, lessThanOrEqualTo (16.0) );
注释:lessThanOrEqualTo匹配符表明如果所测试的数值testedNumber小于等于16.0则测试通过

 

collection相关匹配符

1、assertThat( mapObject, hasEntry( "key", "value" ) );
注释:hasEntry匹配符表明如果测试的Map对象mapObject含有一个键值为"key"对应元素值为"value"的Entry项则测试通过
2、assertThat( iterableObject, hasItem ( "element" ) );
注释:hasItem匹配符表明如果测试的迭代对象iterableObject含有元素“element”项则测试通过
3、assertThat( mapObject, hasKey ( "key" ) );
注释: hasKey匹配符表明如果测试的Map对象mapObject含有键值“key”则测试通过
4、assertThat( mapObject, hasValue ( "key" ) );
注释:hasValue匹配符表明如果测试的Map对象mapObject含有元素值“value”则测试通过

© 著作权归作者所有

谢思华
粉丝 77
博文 221
码字总数 152858
作品 0
广州
程序员
私信 提问
Junit4 使用(在eclipse上) author: Blue

如果写了一个类,想测试一下有没有bug,可以用main方法去测试。但是main方法缺点很多,不是理想的做单元测试的途径——方法不能一起运行,且测试结果多数要通过程序员自己观察才可以判定。 ...

晨曦之光
2012/05/23
523
1
junit4备忘录

简介 JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 测试用例不是用来证明你(的逻辑)是对的,而是用来...

林湾村龙猫
2016/11/26
23
0
扩展 JUnit4 以促进测试驱动开发

简介: 在采用测试驱动开发的项目中,有一个经常困扰开发者的问题是:当存在大量的测试用例时,一次运行完所有的测试用例要花费很长的时 间,采用 TestSuite 来组织测试用例的方式缺乏灵活性...

红薯
2010/07/26
998
3
单元测试基本

单元测试是编写测试代码,用来检测特定的、明确的、细颗粒的功能。单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的。 单元测试不仅仅用来保证当前代码的正确性,更重要的是...

Reborn-D
2016/11/28
23
0
JUnit4使用总结及Assert

JUnit3、JUnit4、JUnit5 写这篇文章的时候JUnit5正式版刚刚发布不久。 对于JUnit3(了解): 1、每一个测试类都需要继承自TestCase 2、每一个测试方法都要以test开头 3、初始化方法名必须是:s...

一剑围城
2017/09/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
7
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部