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: [email protected]
* @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: [email protected]
* @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: [email protected]
* @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: [email protected]
* @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: [email protected]
* @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: [email protected]
* @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();
}
}