转载请注明本文出自大苞米的博客(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否则抛出异常。

copy

 

public calculate {

  • add( a,  b) {
  • a + b;
  • divide( a,  b)  Exception {
  • ( == b) {
  • Exception();
  • }
  • a / b;
  • }
  • }

接着写一个简单的JUnit测试类,对他进行单元测试

copy

 

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。如果对于定义注解不清楚的同学请看我之前写的文章。

copy

 

@Target
@Retention
public Before {

  • }
copy

 

@Target
@Retention
public Test {

  • Class<?  Object> expected()  String.;
  • }
copy

 

@Target
@Retention
public After {

  • }

三个很简单的注解,都标注只能修饰方法,保留策略为运行时,这样可以被反射读取到。

只有Test注解中定义了一个属性,类型可以为任何类型的Class对象,默认值为String类型的Class对象。

接下来定义我们模拟的JUnit类,这里为了方便我将所有能用到的都写在一个MyJUnit类中。他对外只有一个构造方法和一个run方法。还有一个对比用的assertEquals方法

copy

 

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类都定义好后可以写测试的方法了,和之前的测试方法没有区别,只是这次导包导入的都是我们自定义的包。

copy

 

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方法传入的预期值和实际值不同。

下面看最后的运行类。

copy

 

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中反射和注解的使用,而且在很多框架中很多都利用了反射和注解这对黄金组合来实现一些如权限判断,调用等等很多功能。所以说反射还是值得好好学习和研究的。

反射学习总结系列博文断断续续写了一个多月,这篇是最后一篇了。通过这一个月的学习对反射的基本概念和使用算是有了一个了解,有时间还需要深入的学习。

这里需要提一下,学习的资料主要是从网上下的系列视频。主要借鉴了其中中的思路和一些概念类的东西,但是文章中的例子都是我自己写的。最后向大家推荐一下这个视频吧,不是做广告,讲的确实不错,讲课的老师叫张龙,口齿清晰讲的很深入。在大学时看的马士兵的视频,比较适合入门,这个适合晋级。再想继续晋级就得看书了,哈哈。

由于一些烂七八糟的原因我就不提供这个视频的下载地址了,如果需要请自己上网搜,或者留下邮箱我给链接发过去。

最后把本例的代码上传了,导入就可以运行。点击打开下载链接

Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)的更多相关文章

  1. Java高级特性 第10节 IDEA和Eclipse整合JUnit测试框架

    一.IDEA整合Junit测试框架 1.安装插件 打开File菜单的下拉菜单settings[设置] : 点击左侧Plugins[插件]菜单 在输入框中输入JUnitGenerator 2.0,点击I ...

  2. Java - Junit单元测试框架

    简介 Junit : http://junit.org/ JUnit是一个开放源代码的Java语言单元测试框架,用于编写和运行可重复的测试. 多数Java的开发环境都已经集成了JUnit作为单元测试的 ...

  3. Android(java)学习笔记106-2:反射机制

    1.反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

  4. Android(java)学习笔记46:反射机制

    1. 反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称 ...

  5. JAVA自动化之Junit单元测试框架详解

    一.JUnit概述&配置 1.Junit是什么? Junit是一个Java 编程语言的开源测试框架,用于编写和运行测试.官网 地址:https://junit.org/junit4/ 2.Ma ...

  6. c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习

    c#中@标志的作用   参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...

  7. Java基础学习总结(45)——JAVA单元测试工具比较

    1.简介 jtest是parasoft公司推出的一款针对java语言的自动化白盒测试工具,它通过自动实现java的单元测试和代码标准校验,来提高代码的可靠性.Jtest先分析每个java类,然后自动生 ...

  8. Java Junit测试框架

    Java    Junit测试框架 1.相关概念 Ø JUnit:是一个开发源代码的Java测试框架,用于编写和运行可重复的测试.它是用于单元测试框架体系xUnit的一个实例(用于java语言).主要 ...

  9. Java 工具 JUnit单元测试

    Java 工具 JUnit单元测试 @author ixenos 1.1.   JUnit单元测试框架的基本使用 一.搭建环境: 导入junit.jar包(junit4) 二.写测试类: 0,一般一个 ...

随机推荐

  1. Oracle primary key&foreign key

    --主键 alter table tablename1 add constraint pk_tablename1 primary key(column1);--增加数据表1的主键column1,如果是 ...

  2. C/C++(数据结构栈的实现)

    栈的实现 特点FILO(先进后出) 假设栈的空间为8 top == 0 不能出栈,已到栈底 top == 8 不能入栈,已到栈顶 top始终指向一个待插入的位置 push操作,1.写入数据,2.top ...

  3. matplotlib散点图笔记

    定义: 由一组不连续的点完成的图形 散点图: 包含正相关性,负相关性和不相关性. 散点图生成函数: plt.scatter(x,y) 演示代码如下: import numpy as np import ...

  4. SpringJunit测试类 BaseTest(转)

    /** * * * @author Jerval * @date 2011-2-17 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfig ...

  5. 国内搜索大哥iOS面试题

    每一次面试之后都会对问到的面试题进行总结. 这篇总结的是我面试某大型搜索公司的iOS面试题.一面(15min)+二面(30min).并拿到实习offer.当然在今天这个特殊的节日,祝大家新年快乐.希望 ...

  6. actionBar-双行字体大小修改

    <style name="BackupRestore.Theme.Person" parent="@style/BackupRestore.Theme"& ...

  7. Vue前后端分离常用JS函数点(一)

    1.筛选过滤:array.filter(function(val){});  会把array中符合规则的数组元素按array里面的元素顺序保留下来. // 官方解释:按返回true或者false,把不 ...

  8. 洛谷 P1689 方程求解

    P1689 方程求解 题目描述 给一个方程,形如X+Y=Z或X-Y=Z.给出了其中两个未知数,请求出第三个数.未知数用‘?’表示,等式中也许会出现一些多余的空格. 输入输出格式 输入格式: 一行,方程 ...

  9. ios 获取手机信息(UIDevice、NSBundle、NSLocale)

    iOS的SDK中提供了UIDevice.NSBundle,NSLocale. UIDevice        UIDevice提供了多种属性.类函数及状态通知,帮助我们全方位了解设备状况. 从检測电池 ...

  10. 九度OJ—题目1032:ZOJ

    题目描写叙述: 读入一个字符串.字符串中包括ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出.当某个字符用完时,剩下的仍然依照ZOJ的顺序输出. 输入: 题目包括多组用例,每组用例占一行,包括ZOJ ...