Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持!
本文是Java反射学习总结系列的最后一篇了,这里贴出之前文章的链接,有兴趣的可以打开看看。
http://blog.csdn.net/a396901990/article/category/2302221
本文介绍了如何利用反射和注解去简单的模拟JUnit4单元测试框架,之所以选择JUnit4是因为4.0以后最大的改进就是使用了注解。需要注意的是这里并不是完全的模拟,只是简单实现了一下Runner类和JUnit注解相关的工作流程。所以本文的主要目的是介绍反射和注解的使用。废话不多说,直接进入正文。
首先来看一个Junit单元测试的小例子:
先定义一个简单的类,里面只有一个add计算加法的方法和一个divide计算除法的方法,divide方法需要判断除数不能为0否则抛出异常。
public calculate {
- add( a, b) {
- a + b;
- divide( a, b) Exception {
- ( == b) {
- Exception();
- }
- a / b;
- }
- }
接着写一个简单的JUnit测试类,对他进行单元测试
import org.junit.Assert.*;
- org.junit.After;
- import import public calulateTest {
- calculate cal;
- before() Exception {
- cal = calculate();
- );
- System.out.println(
- after() Exception {
- addTest() {
- System.out.println( result = cal.add(, );
- , result);
- }
- (expected = Exception.)
- div() Exception {
- System.out.println( , );
- }
- }
执行结果为:
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。如果对于定义注解不清楚的同学请看我之前写的文章。
@Target @Retention public Before {
- }
@Target @Retention public Test {
- Class<? Object> expected() String.;
- }
@Target @Retention public After {
- }
三个很简单的注解,都标注只能修饰方法,保留策略为运行时,这样可以被反射读取到。
只有Test注解中定义了一个属性,类型可以为任何类型的Class对象,默认值为String类型的Class对象。
接下来定义我们模拟的JUnit类,这里为了方便我将所有能用到的都写在一个MyJUnit类中。他对外只有一个构造方法和一个run方法。还有一个对比用的assertEquals方法
public MyJUnit {
- List<Method> beforeMethod;
- List<Method> afterMethod;
- List<Method> testMethod;
- List<Exception> exceptions;
- Object object;
- Class<?> testClass;
- MyJUnit(String testName) {
- ();
- {
- beforeMethod = ArrayList<>();
- ArrayList<>();
- testMethod = ArrayList<>();
- ArrayList<>();
- testClass = Class.forName(testName);
- getAllMethods();
- (Exception e) {
- getAllMethods() {
- (Method m : methods) {
- (m.isAnnotationPresent(Before.)) {
- (m.isAnnotationPresent(After.)) {
- (m.isAnnotationPresent(Test.)) {
- run() {
- (Method method : testMethod) {
- runTest(method);
- (exceptions.size() == ) {
- );
- } {
- (Exception e : exceptions) {
- System.out.println();
- );
- e.printStackTrace();
- runTest(Method method) {
- {
- runBefores();
- (Exception e) {
- e.getMessage();
- RuntimeException(
- runAfters() Exception {
- (Method m : afterMethod) {
- Object[] {});
- }
- runBefores() Exception {
- (Method m : beforeMethod) {
- m.invoke(object, Object[] {});
- runTestMethod(Method method) {
- passCheck = ;
- {
- Test testAnnotation = method.getAnnotation(Test.);
- (testAnnotation.expected().newInstance() Exception) {
- ;
- }
- (Exception e) {
- (passCheck) {
- ;
- } {
- addExceptions(Exception e) {
- assertEquals(Object expected, Object actual) {
- (expected.equals(actual)) {
- ;
- } {
- Exception());
- }
- }
注解和JUnit类都定义好后可以写测试的方法了,和之前的测试方法没有区别,只是这次导包导入的都是我们自定义的包。
import gxy.test.Junit.MyJUnit.*;
- public MyCalulateTest {
- Calculate cal;
- before() Exception {
- Calculate();
- System.out.println();
- after() Exception {
- System.out.println(
- addTest() {
- result = cal.add(, );
- assertEquals(, result);
- (expected = Exception.)
- divTest() Exception {
- , );
- }
- }
为了检验测试效果,这里对于addTest的方法中assertEquals方法传入的预期值和实际值不同。
下面看最后的运行类。
public main(String[] args) Exception {
- MyJUnit myJUnit = MyJUnit();
- }
只有2行代码,传入需要测试的类的名字,然后执行run方法。
测试结果:
------------------
before test
do add test
after test
------------------
before test
do divide test
after test
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
测试不通过,错误的内容为:
java.lang.Exception: 预期值与实际值不相等
at gxy.test.Junit.MyJUnit.assertEquals(MyJUnit.java:139)
at gxy.test.Junit.MyCalulateTest.addTest(MyCalulateTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at gxy.test.Junit.MyJUnit.runTestMethod(MyJUnit.java:119)
at gxy.test.Junit.MyJUnit.runTest(MyJUnit.java:85)
at gxy.test.Junit.MyJUnit.run(MyJUnit.java:66)
at gxy.test.Junit.FinalTest.main(FinalTest.java:13)
本文只是简单的模拟了一下在JUnit中反射和注解的使用,而且在很多框架中很多都利用了反射和注解这对黄金组合来实现一些如权限判断,调用等等很多功能。所以说反射还是值得好好学习和研究的。
反射学习总结系列博文断断续续写了一个多月,这篇是最后一篇了。通过这一个月的学习对反射的基本概念和使用算是有了一个了解,有时间还需要深入的学习。
这里需要提一下,学习的资料主要是从网上下的系列视频。主要借鉴了其中中的思路和一些概念类的东西,但是文章中的例子都是我自己写的。最后向大家推荐一下这个视频吧,不是做广告,讲的确实不错,讲课的老师叫张龙,口齿清晰讲的很深入。在大学时看的马士兵的视频,比较适合入门,这个适合晋级。再想继续晋级就得看书了,哈哈。
由于一些烂七八糟的原因我就不提供这个视频的下载地址了,如果需要请自己上网搜,或者留下邮箱我给链接发过去。
最后把本例的代码上传了,导入就可以运行。点击打开下载链接
转载于:https://www.cnblogs.com/Free-Thinker/p/6397419.html
Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)相关推荐
- Java基础学习总结(130)——使用WebSocket导致jUnit单元测试报No suitable default RequestUpgradeStrategy found错误的解决方法
若在SpringMVC项目中使用了WebSocket,在运行jUnit单元测试时,可能会报如下错误: Caused by: java.lang.IllegalStateException: No su ...
- Java之单元测试(JUnit单元测试框架)
一.概述 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,所以单元测试就是针对Java方法的测试,进而检查方法的正确性. 常规测试有什么问题? 只有一个main方法,如果 ...
- Java基础学习13--注解和反射
一.注解Annotation 1.注解概述 注释+解释:不是程序本身,而是对其做出解释,并能被其它程序读取. 格式:@注释名(参数) 定义注解的关键字:@interface 2.常见的内置注解: @O ...
- 《Effective Java》——学习笔记(泛型枚举和注解)
泛型 第23条:请不要在新代码中使用原生态类型 如果使用原生态类型,就失掉了泛型在安全性和表述性方面的所有优势,比如不应该使用像List这样的原生态类型,而应该使用如List<Object> ...
- Java高级特性 第10节 IDEA和Eclipse整合JUnit测试框架
一.IDEA整合Junit测试框架 1.安装插件 打开File菜单的下拉菜单settings[设置] : 点击左侧Plugins[插件]菜单 在输入框中输入JUnitGenerator 2.0,点击I ...
- 尚学堂JAVA高级学习笔记_1/2
尚学堂JAVA高级学习笔记 文章目录 尚学堂JAVA高级学习笔记 写在前面 第1章 手写webserver 1. 灵魂反射 2. 高效解析xml 3. 解析webxml 4. 反射webxml 5. ...
- java反射 pdf_java反射学习笔记整理.pdf
java反射学习笔记整理.pdf 还剩 15页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: Java 反射笔记 ...
- 一起学JAVA 反射学习(超详细)
1 什么是反射? Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",也有称作"自省&quo ...
- Java反射学习总结五(Annotation(注解)-基础篇)
Annotation(注解)简单介绍: 注解大家印象最深刻的可能就是JUnit做单元測试,和各种框架里的使用了. 本文主要简介一下注解的用法,下篇文章再深入的研究. annotation并不直接影响代 ...
- Java学习十四,JDBC,反射
目录 1.JDBC入门 1.1.JDBC的概念 1.1 JDBC的基本操作 1.2 JDBC的API 1.3 JDBC的CRUD操作(createStatement类) 1.4 JDBC防sql注入( ...
最新文章
- Linux Performance
- kali linux 安装 Mysql Can‘t read from messagefile 报错解决方案
- oracle查询表的字段类型有哪些,oracle中查询表的信息,包括表名,字段名,字段类型,主键(精)...
- 因为应用程序的并行配置不正确 sxstrace
- netapp做内网穿透有问题
- Hibernate学习笔记(一)
- bugku 杂项 就五层你能解开吗_9.65米解放龙V杂项危险废物厢式运输车62
- 【Elasticsearch】Elasticsearch:聚合 操作
- setwindowpos怎么改变z序_Windows转Mac——操作习惯的改变!
- python数据读写 panda(to_csv和read_csv)【读取dat文件】【写入dat文件】【非csv文件并且有多列数据时】
- 软考资料-软件设计师
- 只需要几行代码就可以轻松实现OCR图片转文字
- 如何解决卸载驱动之后又重新装的问题
- Java复习 思维导图
- 怎样系统的学习计算机编程,如何学习电脑编程
- yuki翻译器钩子_YUKI GALGAME翻译器
- 东芝复印机2303出现f070_东芝复印机常见故障
- 小白重装系统步骤总结
- VBA变量和函数名中文拼音输入提示
- 惠普m180n故障码04_惠普m180n打印机驱动(解决m180n打印机连接问题)V1.0 免费版
热门文章
- 在一起计时器_拥有计时器的四个怪兽,一个从杰克身上拿的,一个差点打死赛罗...
- 计算机维修报价,求一张电脑维护维修价格表
- idea 新建的java项目没发run_IntelliJ IDEA 如何创建一个普通的java项目,及创建java文件并运行...
- cesium 加载bim模型_BIM+GIS跨界融合,打造智能未来新利器
- linux下运行hadoop,Linux命令行下运行Hadoop单元测试
- Pandas:时间序列数据基本操作和分组
- 极客大学产品经理训练营 产品思维和产品意识 作业2
- The Greatest C++ project
- 406.根据身高重建队列
- 刷新输出缓冲区(C++)