Junit单元测试
测试分类
黑盒测试:
不需要书写代码,刚给输入值,看程序是否能够输出期望的值;
白盒测试:
需要写代码的,关注程序具体的执行流程.
白盒测试
步骤:
定义一个测试类(测试用例)
建议:
测试类名:被测试的类型Test 例如CalculatorTest
包名:xxx.xxx.xx.Test cn.it.test
定义测试方法:可以独立运行
建议:
方法名:test测试的方法名 testAdd()
返回值:void
参数列表:空参
给方法加上注解:@Test
不需要main方法,也可以独立运行一个或者多个方法测试
导入JUnit依赖环境
判定结果
红色:失败
绿色:成功
一般我们会使用断言来操作处理结果
Assert.assertEquals(3,result);
第一值时表示我预计结果是3,result是实际返回值,
如果预计结果和实际结果相同,会绿色否则红色;
补充
@Before:
修饰的方法会在测试方法执行之前被自动执行;
@After
修饰的方法会在测试方法执行之后被自动执行
反射:框架设计的灵魂
框架:半成品软件.可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
将成员变量封装成 Field[] fields数组
将构造方法封装成 Constructor[] cons数组 [坑死chua科特]
将成员方法封装成 Method[] methods数组
好处:
可以在程序运行过程中,操作这些对象
可以解耦,提高程序的可扩展性.
获取Class对象的方式:
1.Class.forname("全类名"): 将字节码文件加载进内存,返回Class对象
(多用于配置文件,将类名定义在配置文件中.读取文件,加载类)
Class cls1=Class.forName("cn.it.domain.Person");
System.out.println(cls1);
2.类名.class: 通过类名的属性class获取
(多用于参数的传递)
Class cls2 = Person.class;
System.out.println(cls2);
3.对象.getClass(): getClass()方法在Object类中定义着
(多用于对象的获取字节码的方式)
Person p=new Person();
Class cls3=p.getClass();
System.out.println(cls3);
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,
不论通过哪一种方式获取的Class对象都是同一个;
Class对象功能
//获取Person的Class对象
Class presonClass = Preson.class;
1获取成员变你们
获取所有public修饰的变量
* Field[] getFields()
获取指定名称的 public修饰的成员变量
* Field getfield(string name)
获取所有成员变量,不考虑修饰符
* Field[] getDeclaredFields()
获取指定名称的成员变量,不考虑修饰符
* Field getDeclaredField(string name)
2.获取构造方法们
* Constructor<?>[] getconstructors()
* Constructor<T> getconstructor(类<?>... parameterTypes)
*
* Constructor<t> getDeclaredConstructor(类<?>... parametertypes)
* Constructor<?>[] getDeclaredConstructors()
3.获取成员方法们:
* Method[] getMethods()
* Method getMethod(string name,类<?>... parameterTypes)
*
* Method[] getDeclaredMethods()
*Method getDeclaredMethod(string name,类<?>... parameterTypes)
4.获取类名
* string[getName()
Field:成员变量
操作:
设置值
void set(Object obj,Object value)
获取值
get (Object obj)
忽略访问权限修饰符的安全检查
setAccessible(true); //暴力反射
Constructor:构造方法
创建对象:
T newInstance(object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:class对象的newInstance方法
Method:方法对象
执行方法卡
object invoke(object obj, object... args)
获取方法名称:
string getName:获取方法名
案例:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
/*1 获取成员变量们
* Field[]getFields() //获取所有public修饰的成员变量;
* Field getfield(string name)//获取指定名称的 public修饰的成员变量
忽略访问权限修饰符的安全检查
setAccessible(true); //暴力反射
* Field[]getDeclaredFields()//获取所有成员变量,不考虑修饰符
* Field getDeclaredField(string name)//获取指定名称的成员变量,不考虑修饰符
2. 获取构造方法们
* Constructor < ?>[]getconstructors()
* Constructor < T > getconstructor(类 < ? >...parameterTypes)
*Constructor<t> getDeclaredConstructor (类 < ? >...parametertypes)
*Constructor<?>[] getDeclaredConstructors ()
3. 获取成员方法们:
*Method[] getMethods ()
* Method getMethod(string name, 类 < ? >...parameterTypes)
*
*Method[] getDeclaredMethods ()
* Method getDeclaredMethod(string name, 类 < ? >...parameterTypes)
4. 获取类名
* string[getName()
*/
//获取Person的Class对象
Class presonClass = Preson.class;
//Field[] getField()获取所有public修饰的变量
Field[] fields = presonClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-------");
// Field getfield(string name)
Field a = presonClass.getField("a");
//获取成员变量a的值
Preson p=new Preson();
Object value = a.get(p);
System.out.println(value);
//设置"a"的值
a.set(p,"张三");
System.out.println(p);
System.out.println("=========");
//Field[] getDeclaredFields():获取所有成员变量,不考虑修饰符
Field[] declaredFields = presonClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
Field d = presonClass.getDeclaredField("d");//d为私有成员变量
//忽略访问权限修饰符的安全检查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
System.out.println("+++++++++");
//获取一个构造器对象constructor
Constructor constructor = presonClass.getConstructor(String.class,int.class);//Preson构造方法中传递的参数类型
System.out.println(constructor);
//创建对象
Object preson = constructor.newInstance("李四", 30);
System.out.println(preson);
System.out.println("--------------------");
//获取一个构造器对象constructor---空参构造方法
Constructor constructor1 = presonClass.getConstructor();//Preson构造方法中传递的参数类型
System.out.println(constructor1);
//创建对象
Object preson1 = constructor1.newInstance();
System.out.println(preson1);
//获取一个构造器对象constructor---空参构造方法--简化
Object o = presonClass.newInstance();
System.out.println(o);
//也有暴力反射
constructor1.setAccessible(true);
//获取指定名称的方法
Method eat = presonClass.getMethod("eat");
Preson p1=new Preson();
//执行方法
eat.invoke(p1);
//获取指定名称的带参方法
Method eat1 = presonClass.getMethod("eat", String.class);
eat1.invoke(p1,"饭");
//获取所有public修饰的方法
Method[] methods = presonClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取类名
String className = presonClass.getName();
System.out.println(className);
}
案例需求:
写一个框架,不改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//加载配置文件
//创建Properties对象
Properties pro=new Properties();
//获取class目录下的配置文件
InputStream is = Preson_Test.class.getClassLoader().getResourceAsStream("pro.properties");
pro.load(is);
//获取配置文件中定义的数据
String classname = pro.getProperty("classname");
String methodName = pro.getProperty("methodName");
//加载该类进内存
Class aClass = Class.forName(classname);
//使用获取空参构造方法简化来获取放方法对象
Object o = aClass.newInstance();
//获取指定名称的方法
Method method = aClass.getMethod(methodName);
//执行方法
method.invoke(o);
}
pro.properties文件
classname=ClassTest.Preson
methodName=eat
注解
概念:说明程序的。 给计算机看的
注释:用文字描述程序的。给程序员看的
*定义:注解(Annotation)也叫元数据。一种代码级别的说明了它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用分类:
①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【override】
JDK中预定义的一些注解
@Override :检测被该注解标注的方法是否是继承自父类(接口)的
@Deprecated:该注解标注的内容,表示已过时
@suppressWarnings:压制警告
一般传递参数all @SuppressWarnings("all")
自定义注解
格式:
元注解
public @interface 注解名称{}
本质:注解本质上就是一个接口,该接口默认继承Annotation接口
* public interface MyAnno extends java.lang.annotation.Annotation {}
属性:接口中的抽象方法
*要求:
1.属性的返回值类型
基本数据类型
String
枚举
注解
以上类型的数组
2.定义了属性,在使用时需要给属性赋值
1 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,
可以不进行属性的赋值。
2.如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,
直接定义值即可。
3.数组赋值时,值使用{包裹。如果数组中只有一个值,则{}省略
元注解:用于描述注解的注解
* @Target:描述注解能够作用的位置
ElementType取值:
TYPE:可以作用于类上
METHOD:可以作用于方法上
FIELD:可以作用于成员变量上
@Retention:描述注解被保留的阶段
@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
@Documented:描述注解是否被抽取到api文档中
@Inherited:描述注解是否被子类继承
在程序使用(解析)注解:获取注解中定义的属性值
1.获取注解定义的位置的对象 (class,Method,Field)
2.获取指定的注解
getAnnotation(Class)
//其实就是在内存中生成了一个该注解接口的子类实现对象
public class ProImpl implements Pro{
public string className(){
return "cn.itcast.annotation.Demo1";
}
public string methodName(){
return "show";
}
}
3.调用注解中的抽象方法获取配置的属性值