JUnit4用法用例

0x00 JUnit概述

在软件开发领域,从来就没有如此少的代码起到了如此重要的作用。

这句话源自Martin Fowler的评价,从这句话可以看出JUnit的特性和重要性。关于JUnit更为详细的阐述可以参见JUnit4IBMJUnit4Eclipse,JUnit的源码参见JUnit4Github。本文也是在上述文献的基础上,旨在更加简单快捷使用,总结出一份JUnit的基本用例。

0x01 JUnit基本用例

本用例只是基于JUnit4的用法,使用最基本且最易懂的注释方式进行阐述。

package com.voidsun.junit.test;

// 使用static修饰,类似断言Assert.assertEquals(x,y),则简化为assertEquals(x,y)
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import org.junit.Ignore;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;

// 测试类的执行顺序注解 “@FixMethodOrder(value)” 
// 默认(MethodSorters.DEFAULT),按方法名(MethodSorters.NAME_ASCENDING)和JVM(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class JunitTest{

    // 该类中的测试方法运行之前刚好运行一次
    @BeforeClass
    public static void initBeforClass() {
        // 可以初始化Bean,可以是公共数据库连接、网络连接,也可以是公用数据结构等等
    }

    // 该类中的所有测试都运行之后刚好运行一次
    @AfterClass
    public static void tearDownClass() {
        // 可以关闭数据库连接、还原初始数据等等
    }

    // 在测试方法之前运行
    @Before
    public void initSetUp(){
        // 可以注释多个方法,这些方法都在每个测试之前运行
        // 可以初始化字段值、打开日志记录等等
    }

    // 在每个测试方法之后运行
    @After
    public void tearDownAfter(){
        // 可以注释多个清除方法
    }

    // 测试方法,根据测试类的执行顺序,一般方法命名规范:testxxxNAME,xxx为数字(越小越先),NAME一般是实际测试的方法名,或者需要测试的其他方法
    @Test
    public void test001JunitTest(){
        // 断言方法简述列表,均不对参数进行说明
        assertTrue(); // 判断condition是否为true
        assertFalse(); // 判断condition是否为false
        fail(); // 测试失败,抛出消息
        assertEquals(); // 判断两个对象是否相等,支持Object、long、double、Object[]、byte[]、char[]、short[]、int[]、long[]、double[]、float[]等
        assertNotEquals(); // 判断两个对象是否不相等,支持Object、long、double、Object[]、byte[]、char[]、short[]、int[]、long[]、double[]、float[]等
        internalArrayEquals(); // 判断两个对象数组是否相等
        assertNotNull(); // 判断某个对象是否不为NULL
        assertNull(); // 判断某个对象是否为NULL
        assertSame(); // 判断两个对象是否引用相同对象
        assertNotSame(); // 判断两个对象是否引用不是同一个对象
        assertThat(); // 
        ...
    }

    // 声明该异常是预期的
    @Test(expected=ArithmeticException.class) 
    public void test002JunitExpectedTest(){
        // 如果该异常没有抛出(或者抛出了一个不同的异常),那么测试就将失败。但是如果您想要测试异常的详细消息或其他属性,则仍然需要使用旧式的try-catch 样式。

        // 旧式的try-catch 样式
        try {
            int n = 1 / 0;
            fail("Divided by zero!");
        }catch (ArithmeticException ae) {
               assertNotNull(ae.getMessage());
            }
    }

    // 超时时间测试
    @Test(timeout=500)
    public void test003JunitTimeOutTest(){
        // 测试运行的时间超过指定的毫秒数,则测试失败
        // 可以测试性能、可以是测试调用某个服务和方法超时等等
    }

    // 被忽略的测试
    @Ignore
    public void test004JunitIgnore(){
        // 可以是想要跳过的运行时间长的测试方法、调用远程或者第三方的服务等等
    }
}

当一个项目中存在很多个测试代码,你需要根据一些条件去执行你的部分测试代码(例如测试查询类的、调用类的等),即打包测试。则可自己编写Runner运行器,通过@SuiteClasses进行集成打包测试,基本用法用例如下:

package com.voidsun.junit.test.suite;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import com.voidsun.junit.test.JunitTest_T1;
import com.voidsun.junit.test.JunitTest_T2;

// 指定一个Runner
@RunWith(value = Suite.class)
// 打包测试
@SuiteClasses(value = { JunitTest_T1.class, JunitTest_T2.class })
public calss JunitTestSuite{
    ...
}

除上述基本功能外,JUnit还有很多其他功能,本文将不赘述。