通过前面的几讲的内容,我们知道了反射还有注解,现在我们就通过Junit深入理解反射与注解的使用方式与情景。
1. Jnuit :Java 单元测试的框架
Junit(3.8, 4.x)的经典版本是3.8 和 4.x版本,前面一个版本基于 反射 来进行的,后面一个版本是 反射+注解 来进行的。
Junit单元测试之后出现了CppUnit、FXUnit、PHPUnit这些基于C++、Flex、PHP的单元测试框架
2. jar包,jar文件其实就是一个压缩包文件,是将一大堆的.class文件打包成一个jar包方便用户使用,用户只要导入jar包就可以使用这些文件.class文件了。
3. 下面我们就通过Jnuit的简单的两个例子来加深对反射和注解的理解
1) 新建一个Java项目,同时添加Junit的jar包. 右击项目 --> build path --> Configure Build path --> 点击Libraries选项卡 --> add Library --> 选择Junit --> 选择Junit版本3。则添加好了Junit包,如下图所示
package com.ahuier.junit; import junit.framework.TestCase; //jnuit4.0 之后包名改了 /* * 要使用Junit,则必须继承其父类TestCase */ public class Test extends TestCase{ //这个版本3的Junit有个约定,我们写的测试方法要以"test"开头,否则,Jnuit测试通不过 public void testAdd(){ System.out.println("Hello World!"); } public void testSubtract(){ System.out.println("welcome"); } }
执行 Run as - -> Junit Test
输出:Hello World! 和 welcome,同时弹出一个绿色框,如下图所示:
弹出绿色框表示程序单元测试通过,在Jnuit领域里面有一个名言:Keep the bar green to keep the code clean.[保持bar是绿色的以维持代码的整洁性]
【说明】:通过上面这个例子,为什么我们在上面定义的方法用Jnuit编译会自动执行呢?
这边就可以理解Junit其实是通过反射来进行的,首先通过反射获得Test类的class对象,通过这个对象就可以获得类中所有方法的method数组,method数组遍历每一个方法,得到method对象,通过getName就可以得到方法的名字,检查方法名字是否已test开头,如果是则调用invoke()方法,则执行,所以它是通过反射来进行的。
2) 现在我们举一例是通过注解和反射的机制进行的Junit例子
再新建一个项目,如上例所示,选择Junit版本为4的jar包
package com.JnuitTest; import org.junit.Test; //这边使用Jnuit4之后,报名改为这个了 public class Test2 { @Test public void hello(){ System.out.println("hello world!"); } }
编译执行 :hello world! 如下图所示:比较与上一个例子的不同,这边只要通过注解@Test ,即便不继承TestCase,不以"test"开头,同样都可以通过Junit单元测试,是什么原因呢?
答案同样是因为Junit中使用反射和注解机制进行的。JUnit4 的执行的一般流程:
a) 首先获得待测试类所对应的 Class 对象。
b) 然后通过该 Class 对象获得当前类中所有 public 方法所对应的 Method 数组。
c) 遍历该 Method 数组,取得每一个 Method 对象
d) 调用每个 Method 对象的 isAnnotationPresent(Test.class)方法,判断该方法是否被Test注解所修饰。
e) 如果该方法返回 true,那么调用 method.invoke()方法去执行该方法,否则不执行。
【总结】:没有反射,很多框架就不存在了。(No Reflection,No most frameworks)。
4. Junit单元测试不是为了证明你是对的,而是证明你没有错误。
5. 有一本书名为 Writing Secure Code(编写安全的代码)这样写输入框的:Input is evil。(用户的输入是邪恶的)
6. Junit的官方网址:http://www.junit.org/