设置密码

验证码错误,请重新填写

免费建站旅程马上开始

开始建站
建站中

已有帐号?直接登录

首页>森动学院>网站建设教程 > 用反射和注解模拟JUnit测试类
用反射和注解模拟JUnit测试类
发布时间: 2014-06-24
先来说一下理论:JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。

本文介绍了如何利用反射和注解去简单的模拟JUnit4单元测试框架,之所以选择JUnit4是因为4.0以后最大的改进就是使用了注解。需要注意的是这里并不是完全的模拟,只是简单实现了一下Runner类和JUnit注解相关的工作流程。所以本文的主要目的是介绍反射和注解的使用。废话不多说,直接进入正文。

看一个Junit单元测试的小例子:
先定义一个简单的类,里面只有一个add计算加法的方法和一个divide计算除法的方法,divide方法需要判断除数不能为0否则抛出异常。

[java] view plaincopy 
public class calculate {  
  
    public int add(int a, int b) {  
        return a + b;  
    }  
  
    public int divide(int a, int b) throws Exception {  
        if (0 == b) {  
            throw new Exception("除数不能为0");  
        }  
        return a / b;  
    }  
  
}  
接着写一个简单的JUnit测试类,对他进行单元测试

[java] view plaincopy 
import static org.junit.Assert.*;  
import org.junit.After;  
import org.junit.Before;  
import org.junit.Test;  
  
public class calulateTest {  
  
    private calculate cal;  
  
    @Before     //使用JUint提供的注解标注此方法在执行测试方法前执行  
    public void before() throws Exception {  
        cal = new calculate();  
        System.out.println("------------------");  
        System.out.println("before test");  
    }  
  
    @After      //使用JUint提供的注解标注此方法在执行测试方法后执行  
    public void after() throws Exception {  
        System.out.println("after test");  
    }  
  
    @Test       //使用JUint提供的注解标注此方法为需要测试的方法  
    public void addTest() {  
        System.out.println("do add test");  
        int result = cal.add(10, 20);  
        //判断result和预期的值是否相等,在此例中如果result等于30则测试通过  
        assertEquals(30, result);  
    }  
      
    @Test(expected = Exception.class)  //使用JUnit的Test注解,并且判断预期值是否是Exception  
    public void div() throws Exception {  
        System.out.println("do divide test");  
        cal.divide(1, 0);   //调用1除以0,抛出异常  
    }  
  
}  
执行结果为:

before test
do add test
after test
------------------
before test
do divide test
after test



下面我们就用反射和注解的知识来模拟JUnit对于上面例子的实现。

这里先不着急看代码,先看梳理一下思路。

1.JUnit只可以知道一件事,那就是待测试类的名字,其他的一概不知。所以我们只能利用测试类的名字作为切入口

2.通过测试类的名字,使用反射去获取他的Class对象

3.然后通过该Class对象获得当前类中所有方法的Method数组

4.遍历这个Method数组,取得每一个Method对象

5.调用每一个Method对象的isAnnotationPresent(Annotation.class)方法,判断该方法是否被指定注解所修饰

6.本例中根据不同的注解,来判断调用方法的顺序。

7.如果Test注解有属性的话,则判断方法执行后的返回值,如果返回值等于预期的注解属性也就是expected = Exception.class则测试通过。

8.最后还有一个assertEquals方法,他去判断预期值和实际值是否相等来决定测试是否通过。


大致的思路有了,我们就可以开始模拟它了。

首先定义3个注解,分别是Before,Test,After。如果对于定义注解不清楚的同学请看我之前写的文章。

[java] view plaincopy 
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface Before {  
      
}  
[java] view plaincopy 
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface Test {  
    Class<? extends Object> expected() default String.class;  
}  
[java] view plaincopy 
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface After {  
  
}  
三个很简单的注解,都标注只能修饰方法,保留策略为运行时,这样可以被反射读取到。
只有Test注解中定义了一个属性,类型可以为任何类型的Class对象,默认值为String类型的Class对象。