单元测试Junit使用详解

1、Junit 是什么?

  JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。

  注意:Junit 测试也是程序员测试,即所谓的白盒测试,它需要程序员知道被测试的代码如何完成功能,以及完成什么样的功能

2、Junit 能做什么?

  我们知道 Junit 是一个单元测试框架,那么使用 Junit 能让我们快速的完成单元测试。

  通常我们写完代码想要测试这段代码的正确性,那么必须新建一个类,然后创建一个 main() 方法,然后编写测试代码。如果需要测试的代码很多呢?那么要么就会建很多main() 方法来测试,要么将其全部写在一个 main() 方法里面。这也会大大的增加测试的复杂度,降低程序员的测试积极性。而 Junit 能很好的解决这个问题,简化单元测试,写一点测一点,在编写以后的代码中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。

3、Junit 的用法

首先介绍 Junit 的几种类似于 @Test 的注解:

  1.@Test: 测试方法

    a)(expected=XXException.class)如果程序的异常和XXException.class一样,则测试通过
    b)(timeout=100)如果程序的执行能在100毫秒之内完成,则测试通过

  2.@Ignore: 被忽略的测试方法:加上之后,暂时不运行此段代码

  3.@Before: 每一个测试方法之前运行

  4.@After: 每一个测试方法之后运行

  5.@BeforeClass: 方法必须必须要是静态方法(static 声明),所有测试开始之前运行,注意区分before,是所有测试方法

  6.@AfterClass: 方法必须要是静态方法(static 声明),所有测试结束之后运行,注意区分 @After

 

junit before,beforeClass,after, afterClass的执行顺序

JUnit4使用Java5中的注解(annotation),以下是JUnit4常用的几个annotation: 

  • @Before:初始化方法   对于每一个测试方法都要执行一次(注意与BeforeClass区别,后者是对于所有方法执行一次)
  • @After:释放资源  对于每一个测试方法都要执行一次(注意与AfterClass区别,后者是对于所有方法执行一次)
  • @Test:测试方法,在这里可以测试期望异常和超时时间 
  • @Test(expected=ArithmeticException.class)检查被测方法是否抛出ArithmeticException异常 
  • @Ignore:忽略的测试方法 
  • @BeforeClass:针对所有测试,只执行一次,且必须为static void 
  • @AfterClass:针对所有测试,只执行一次,且必须为static void 
  • 一个JUnit4的单元测试用例执行顺序为: 
  • @BeforeClass -> @Before -> @Test -> @After -> @AfterClass; 
  • 每一个测试方法的调用顺序为: 
  • @Before -> @Test -> @After; 

 

 

 那么上面的例子,我们可以看到,每个 @Test 方法中都有 Calculator c = new Calculator();即类的实例化,那么我们可以将其放入到 @Before 中

 

public class CalculatorTest {

    Calculator c = null;

     

    @Before

    public void testBeforeClass(){

        c = new Calculator();

    }

    @Test

    //测试 add()方法

    public void testAdd(){

        int result = c.add(12);

        //Assert.assertEquals(result, 3);

        //等价于:

        if(result == 3){

            System.out.println("add()方法正确");

        }

    }

     

    @Test

    //测试 sub()方法

    public void testSub(){

        int result = c.sub(21);

        //Assert.assertEquals(result, 1);

        //等价于:

        if(result == 1){

            System.out.println("sub()方法正确");

        }

    }

 

}

  

同理:别的注解用法我们用一个类来看:

public class JunitTest {

    public JunitTest() {

        System.out.println("构造函数");

    }

 

    @BeforeClass

    public static void beforeClass(){

        System.out.println("@BeforeClass");

    }

     

    @Before

    public void befor(){

        System.out.println("@Before");

    }

     

    @Test

    public void test(){

        System.out.println("@Test");

    }

     

    @Ignore

    public void ignore(){

        System.out.println("@Ignore");

    }

     

    @After

    public void after(){

        System.out.println("@After");

    }

     

    @AfterClass

    public static void afterClass(){

        System.out.println("@AfterClass");

    }

}

  结果为:

@BeforeClass

构造函数

@Before

@Test

@After

@AfterClass

  

注意:编写测试类的原则: 

    ①测试方法上必须使用@Test进行修饰

        ②测试方法必须使用public void 进行修饰,不能带任何的参数

        ③新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开

        ④测试类所在的包名应该和被测试类所在的包名保持一致

        ⑤测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖

        ⑥测试类使用Test作为类名的后缀(不是必须)

        ⑦测试方法使用test作为方法名的前缀(不是必须)

 

Junit单元测试执行的顺序

 

  • 在写JUnit测试用例时,有时候需要按照定义顺序执行我们的单元测试方法.
  • 比如如在测试数据库相关的用例时候要按照测试插入、查询、删除的顺序测试。
  • 如果不按照这个顺序测试可能会出现问题,比如删除方法在前面执行,后面的方法就都不能通过测试.
  • 因为数据已经被清空了。而JUnit测试默认的顺序是随机的。所以这时就需要有办法要求JUnit在执行测试方法时按照我们指定的顺序来执行。
  • 按照设计原则,JUnit是不指定测试方法调用执行顺序的。
  • 目前为止,这些方法只是简单地按照反射(reflection) API返回的顺序执行。
  • 但是,使用JVM默认提供的排序是很不明智的,因为Java平台没有指定任何有规律的顺序,
  • 而事实上JDK 7可能会返回一个随机的顺序。
  • 当然,精心编写的测试代码之间并不需要假定任何执行顺序,但有时候,但在某些平台上一个可预测的失败总比随机的失败要好。
  • 本例通过Junit的@FixMethodOrder注解来设定单元测试中方法的执行顺序
  • 可以看到,DefaultOrderTest 和 NotSettingOrderTest 执行结果是一样的
  • JVMOrderTest每次返回不同的结果
  • NameAscOrderTest返回的是按照方法名称的字典序执行的结果

  

不指定顺序 : 从4.11版本开始,JUnit将默认使用一个确定的,但不可预测的顺序。执行顺序同DefaultOrderTest

public class NotSettingOrderTest {

    @Test
    public void one() {
        System.out.println("1");
    }
    @Test
    public void two() {
        System.out.println("2");
    }
    @Test
    public void three() {
        System.out.println("3");
    }
    @Test
    public void four() {
        System.out.println("4");
    }

    /**
     * 无论执行多少次,结果始终为:
     1
     2
     4
     3
     */
}


MethodSorters.DEFAULT : 默认的顺序执行 执行顺序同NotSettingOrderTest@FixMethodOrder(MethodSorters.DEFAULT)

public class DefaultOrderTest {
    @Test
    public void one() {
        System.out.println("1");
    }
    @Test
    public void two() {
        System.out.println("2");
    }
    @Test
    public void three() {
        System.out.println("3");
    }
    @Test
    public void four() {
        System.out.println("4");
    }

    /**
     * 每次执行结果都是:
     1
     2
     4
     3
     */
}


MethodSorters.JVM : 保留测试方法的执行顺序为JVM返回的顺序。每次测试的执行顺序有可能会所不同。

@FixMethodOrder(MethodSorters.JVM)
public class JVMOrderTest {
    @Test
    public void one() {
        System.out.println("1");
    }
    @Test
    public void two() {
        System.out.println("2");
    }
    @Test
    public void three() {
        System.out.println("3");
    }
    @Test
    public void four() {
        System.out.println("4");
    }

    /**
     * 每次执行结果都有可能不一样
     */
}


MethodSorters.NAME_ASCENDING : 按照方法名的字典顺序升序执行

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NameAscOrderTest {
    @Test
    public void one() {
        System.out.println("1");
    }
    @Test
    public void two() {
        System.out.println("2");
    }
    @Test
    public void three() {
        System.out.println("3");
    }
    @Test
    public void four() {
        System.out.println("4");
    }

    /**
     * 无论执行多少次,都是按照方法名字的字典序执行:
     4
     1
     3
     2
     */
}

 

posted @ 2019-03-22 16:47  柚子=_=  阅读(533)  评论(0编辑  收藏  举报