Junit单元测试
junit是白盒测试,步骤:
1.定义一个测试类(测试用例)
2.定义测试方法,返回值为void,参数表为空
3.给方法加@Test注解,或者按Ctrl+Shift+T
4.给测试的方法内加assert断言
@before用于测试初始化(开头),@After用于测试释放资源(结尾)
package test.junit;
public class Calculator {
public int add(int a,int b){
return a+b;
}
public int sub(int a, int b){
return a-b;
}
}
package test.junit;
import org.junit.Test;
import org.testng.Assert;
public class CalculatorTest {
@Test
public void add() {
Calculator c= new Calculator();
int result =c.add(1,2);
System.out.println(result);
Assert.assertEquals(3,result);
}
@Test
public void sub() {
Calculator c= new Calculator();
int result =c.sub(1,2);
System.out.println(result);
}
反射
将类的各个组成部分封装为其他对象,这就是反射机制
Java代码在计算机中经历的三个阶段:
- java的Person类 Person.java文件->字节码 Person.class文件 Source源代码阶段
- Person.class通过类加载器ClassLoader加载到内存,生成Class类对象,Class对象包括:成员变量在Field[]数组中,构造方法在Constructor[]数组中,成员方法在Method[]数组
- Person对象 Runtime运行时阶段
将Person类的成员变量构造方法和成员方法封装成Class类的对象,这就是一种反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
由反射获取对象的三种方式,对应java代码的三个阶段:
1.Source源码阶段:Class.forName(“全类名”),全类名是指包括了包的类名,返回class对象
2.Class类对象阶段:类名.class
3.Runtime运行阶段:对象.getClass()
使用反射机制可以使得不需要修改代码,只需要修改配置文件即可获取响应的类和方法,实例如下
//Reflcet类
package test.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
public class Reflect {
public static void main(String[] args) throws Exception {
//可以创建任意类的对象,可以执行任意类的方法
//1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
//2.在程序中加载配置文件
//创建Properties对象
Properties pro = new Properties();
//利用类加载器获取配置文件路径
ClassLoader classLoader = Reflect.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
// 加载配置文件
pro.load(is);
//3.获取配置文件中定义的数据
String className =pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//4.加载类并创建对象
Class cls = Class.forName(className);
Object obj = cls.newInstance();
//5.获取方法
Method method = cls.getMethod(methodName);
method.invoke(obj);
//pro.properties配置文件
className=test.reflect.Person
methodName = sleep
注解
作用和分类
1.编写文档:使用javadoc来自动根据java文件生成文档
2.代码分析:通过代码里的表示的注解对代码进行分析(使用反射),主要用于替换配置文件
3.编译检查:通过代码里的表示的注释让编译器能够时间基本的编译检查例如@overide
JDK常用的3个注解:
1.@Override:用于标记覆盖父类或父方法的重写
2.@Deprecated:用于版本更新后提示使用者某方法已不建议使用
3.@SuppressWarnings:压制警告
自定义注解:
注解的本质上就是一个接口,该接口默认继承Annotation接口,通过实现反射类Class的getAnnotation()方法来得到一个注解类对象,再调用该注解类对象的抽象方法获得反射中需要创建的类的名和方法的名
自定义注解的格式:
public @interface 注解名称{
属性列表;
}
要求:1.属性列表返回值有这些类型:基本数据类型,String,美剧,注解
2.定义了属性,需要在使用的时候给属性赋值
3.元注解:@target:描述注解能作用的位置
@Retention:描述注解能被保留的阶段
@Documented:描述注解是否被抽取到api文档
@Inherited:描述注解是否能被子类继承
在反射中使用注解来实现类的构建和方法的调用
package test.reflect;
import java.lang.reflect.Method;
@pro(className = "test.reflect.Person",methodName = "sleep")
public class Reflect {
public static void main(String[] args) throws Exception {
//获取该类的字节码文件对象
Class<Reflect> reflectClass = Reflect.class;
//获取注解类的对象
pro an =reflectClass.getAnnotation(pro.class);
//调用注解对象中定义的抽象方法,获取返回值
String className = an.className();
String methodName = an.methodName();
//4.加载类并创建对象
Class cls = Class.forName(className);
Object obj = cls.newInstance();
//5.获取方法
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
}
//注解类的代码
package test.reflect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
描述需要执行的类名和方法名
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface pro {
String className();
String methodName();
}
用注解加反射来实现测试
Calculator类
package reflect02;
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));
}
}
TestCheck类
package reflect02;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.BufferPoolMXBean;
import java.lang.reflect.Method;
/*
简单的测试框架
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
//创建计算器对象
Calculator c =new Calculator();
//获取字节码文件对象
Class cls = c.getClass();
//获取所有的方法
Method [] methods = cls.getMethods();
int number = 0;
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
//判断方法时候有@Check
for(Method method:methods) {
if (method.isAnnotationPresent(Check.class)) {
try {
method.invoke(c);
} catch (Exception e) {
number++;
bw.write(method.getName() + "方法出异常了");
bw.newLine();
}
}
//执行并捕获异常
}
bw.flush();
bw.close();
}
}
Check注解类
package reflect02;
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 {
}