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

一.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”则测试通过

转载于:https://my.oschina.net/xsh1208/blog/176099

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值