浅谈测试之JUnit

JUnit是一个java语言的单元测试框架,是java测试里最基本的框架。java

JUnit的集成

Android Studio建立的工程会自动集成JUnit,在build.gradle中添加相关依赖:git

testImplementation 'junit:junit:4.12'
复制代码

JUnit的示例

测试框架的存在,并非必须的。它们只是为了让咱们写更少的测试代码。看下面示例,你会发现,所谓的单元测试方法,就像咱们初学java时,常写的main方法。github

下面是使用JUnit进行测试的几个例子。数据库

//测试一个有返回值的方法
    @Test
    public void testMethod() {
        int actual = Util.add(1, 2);
        assertEquals(3, actual);
    }
    
    //测试一个没有返回值,有反作用的方法
    @Test
    public void testMethodWithSideEffect() {
        List<String> strings = Arrays.asList("a", "d", "b", "c");
        List<String> excepted = Arrays.asList("a", "b", "c", "d");
        //测试集合工具类的排序方法
        Collections.sort(strings);
        assertEquals(excepted, strings);
    }

    //测试一个方法抛异常的方案1
    @Test
    public void testMethodThrowException(){
        Exception actual = null;
        try {
            Util.throwException();
        }catch (Exception e){
            actual = e;
        }
        assertEquals(IllegalArgumentException.class,actual.getClass());
    }
    
    //测试一个方法抛异常的方案2
    @Test(expected = IllegalArgumentException.class)
    public void testMethodThrowException2() {
        Util.throwException();
    }
复制代码

如你所见,断言是单元测试里经常使用的东西。JUnit经常使用的断言方法,都在org.junit.Assert类里面,下面列出常见的几个断言方法。顾名思义,就很少说了。安全

assertEquals
assertNotEquals
assertArrayEquals
assertTrue
assertFalse
assertNull
assertNotNull
fail
...
复制代码

JUnit的注解

相关内容主要来源于JUnit的源码注释,若有困惑,请参考源码注释。bash

@Test

用于标注public void方法。被这个注解标记的方法,就是一个测试方法。一个测试类里面,能够有多个被@Test标注的测试方法。它们应该彼此独立,互不影响。能够点方法旁边的绿色箭头,单独运行一个测试方法。app

也能够点击当前测试类旁边的箭头,执行测试类下面全部的测试方法。框架

还能够一键运行test包下面的全部测试类。ide

注意:有两种状况会视为测试失败,不然测试成功。工具

1)测试方法抛异常。

2)你能够这样使用@Test(timeout = 100)。设置超时时间,若是超时则视为测试失败。但这种作法是线程不安全的,因此官方推荐使用{@link org.junit.rules.Timeout} rule来代替。

@Before和@After

它们是方法级别的,用于标注public void方法,会在被@Test标注的测试方法的一前一后运行,每调用一个测试方法都会执行一次,也就是@Before->@Test->@After。因此咱们一般会在被@Before标注的方法下作数据的初始化。在被@After标注的方法下,作数据的清除。

@BeforeClass和@AfterClass

相似@Before和@After,但不一样的是它们是类级别,也就是在执行一个测试类的时候只会调用一次,并且被它们标注的方法,必须是public static void方法。这些方法只会运行一次,会被当前测试类里面全部的测试方法共享。当测试都须要一些昂贵的操做的时候,就须要用到这两个注解。虽然,这会让测试的独立性进行了必定的妥协,但有时这是一个有必要的优化操做。好比,数据库的链接和关闭。

@Rule

这是一个很是强大的注解。

@Rule是方法级别的,每一个测试方法执行时都会调用被标注的Rule。

能够标注是public但非静态,且是TestRule子类的成员变量,如:

@Rule
public TemporaryFolder folder= new TemporaryFolder();
复制代码

也能够标注是public但非静态,并且必须返回一个TestRule子类的实例的方法,如:

private TemporaryFolder folder= new TemporaryFolder();
@Rule
public TemporaryFolder getFolder() {
    return folder;
}
复制代码

TestRule是一个接口类,能够利用它,添加自定义的检查,或者执行必要的设置或清理。TestRule能够作@Before、@After、@BeforeClass和@AfterClass这几个注解能作的全部事,但它每每更强大。

junit也为咱们提供了几个TestRule的具体实现,如Timeout、TemporaryFolder。下面给出一个使用示例:

public class Test {
//只须要用@Rule标注一个是TestRule子类的成员变量。
//这样,若是该类中的任意测试方法超过5000ms任未完成,则该测试失败。
@Rule
public Timeout timeout = new Timeout(5000);
//其他代码略...
}
复制代码

咱们也彻底能够实现属于本身的TestRule,将本身测试类里面经常使用的设置或者清理等重复性高的代码,封装进去,简化测试代码。

public class YourRule implements TestRule {
    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                //作一些预先的设置,或者任何你想作的事
                //如数据库表的建立
                ......
                
                //这里就是测试方法(包括了before、after在里面)
                //下面是官方源码里,对Statement接口的描述
                //Represents one or more actions to be taken at runtime in the course
                //of running a JUnit test suite.
                base.evaluate();  
                
                //作一些清理,或者任何你想作的事
                //如数据库表的删除
                ......
            }
        };
    }
}

复制代码

:若是是对TestRule的具体实现仍然感到迷惑,也能够参考官方给出的那几个具体实现。

@ClassRule

@ClassRule和@Rule类似,不一样点是,@ClassRule是类级别的,只能用于标注静态成员(成员变量,成员方法),在执行一个测试类的时候只会调用一次被注解的Rule。

@Ingore

被该注解标记的测试方法,会被忽略,不会被运行。

@FixMethodOrder

测试类的执行顺序可经过对测试类添加注解 “@FixMethodOrder(value)” 。 三种执行顺序可供选择:

MethodSorters.DEFAULT:默认顺序由方法名hashcode值来决定,若是hashcode值同样,就使用MethodSorters.NAME_ASCENDING来排序。

MethodSorters.NAME_ASCENDING:按字符的字典顺序,会始终保持一致。

MethodSorters.JVM:顺序可能因运行而异,说白了就是不固定。

感受这是一个很鸡肋注解。。

后记

文中的相关测试例子,以及更多的测试例子都可以在UnitTest里面找到。

若是你对一些知识点理解不透彻,也许参考更多的博客也未必有用。我建议,你应该去好好翻阅一下官方的源码注释。这或许能帮助你更深刻理解这些东西,毕竟不少博客的描述,就是源自源码注释。

相关文章
相关标签/搜索