Junit单元测试
反射
反射的了解
反射获取字节码class对象的三种方法
反射class对象的功能
获取Field
获取constructor
获取method
获取类名
反射案例
首先,先创建一个配置文件pro.properties
className=cn.itcast.junit.domain.Student
methodName=sleep
然后分布创建一个Student和Person类:
package cn.itcast.junit.domain;
/**
* @Copyright (C), 2020-2020,
* @ClassName: Person
* @Author:
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 19:56
* @Version: V1.0
* @Description: 对该类的描述
*/
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
public void eat(){
System.out.println("eat...");
}
public void eat(String food){
System.out.println("eat..."+food);
}
}
package cn.itcast.junit.domain;
/**
* @Copyright (C), 2020-2020,
* @ClassName: Student
* @Author:
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 20:56`在这里插入代码片`
* @Version: V1.0
* @Description: 对该类的描述
*/
public class Student {
public void sleep(){
System.out.println("sleep...");
}
}
编写框架ReflectTest类:
package cn.itcast.junit.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @Copyright (C), 2020-2020, 青岛农业大学
* @ClassName: ReflectTest
* @Author: 郑嘉琛
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 20:59
* @Version: V1.0
* @Description: 对该类的描述
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
//1.加载配置文件
//1.1创建Properties对象
Properties pro = new Properties();
//1.2加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodNmae = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodNmae);
//6.执行方法
method.invoke(obj);
}
}
注释
注释的概念
JDK内置注解
自定义注解
元注解
解释注解
先创建一个注解类Pro:
package cn.itcast.junit.annotiation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Copyright (C), 2020-2020,
* @ClassName: Pro
* @Author:
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 22:49
* @Version: V1.0
* @Description: 对该类的描述
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
String className();
String methodName();
}
写一个Demo1:
package cn.itcast.junit.annotiation;
/**
* @Copyright (C), 2020-2020,
* @ClassName: Demo1
* @Author:
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 22:52
* @Version: V1.0
* @Description: 对该类的描述
*/
public class Demo1 {
public void show(){
System.out.println("demo1..show...");
}
}
注解类:
package cn.itcast.junit.annotiation;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @Copyright (C), 2020-2020,
* @ClassName: ReflectTest
* @Author:
* @E-mail: 1248164682@qq.com
* @Date: 2020/2/1 20:59
* @Version: V1.0
* @Description: 对该类的描述
*/
@Pro(className = "cn.itcast.junit.annotiation.Demo2",methodName = "show")
public class ReflectTest {
public static void main(String[] args) throws Exception {
//1.解析注解
//1.1获取该类的字节文件对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//2.获取上边的注解对象
//其实就是在内存中生成一个该注解接口的子类实现对象
Pro an = reflectTestClass.getAnnotation(Pro.class);
//3.调用注释对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}
简单的测试框架
检测一个计算器类是否有问题:
计算器类:
package cn.itcast.junit.annotiation.demo;
/**
* 小明定义的计算器类
*/
public class Calculator {
//加法
@Check
public void add(){
String str = null;
str.toString();
System.out.println("1 + 0 =" + (1 + 0));
}
//减法
@Check
public void sub(){
System.out.println("1 - 0 =" + (1 - 0));
}
//乘法
@Check
public void mul(){
System.out.println("1 * 0 =" + (1 * 0));
}
//除法
@Check
public void div(){
System.out.println("1 / 0 =" + (1 / 0));
}
public void show(){
System.out.println("永无bug...");
}
}
自定义注解Check:
package cn.itcast.junit.annotiation.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
测试框架:
package cn.itcast.junit.annotiation.demo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 简单的测试框架
*
* 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
//1.创建计算器对象
Calculator c = new Calculator();
//2.获取字节码文件对象
Class cls = c.getClass();
//3.获取所有方法
Method[] methods = cls.getMethods();
int number = 0;//出现异常的次数
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
for (Method method : methods) {
//4.判断方法上是否有Check注解
if(method.isAnnotationPresent(Check.class)){
//5.有,执行
try {
method.invoke(c);
} catch (Exception e) {
//6.捕获异常
//记录到文件中
number ++;
bw.write(method.getName()+ " 方法出异常了");
bw.newLine();
bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
bw.newLine();
bw.write("异常的原因:"+e.getCause().getMessage());
bw.newLine();
bw.write("--------------------------");
bw.newLine();
}
}
}
bw.write("本次测试一共出现 "+number+" 次异常");
bw.flush();
bw.close();
}
}