单元测试
概述、Junit框架快速入门
- 单元测试
- 就是针对最小的单元(方法),编写测试代码对其进行正确性测试
- 之前是如何进行单元测试的?存在什么问题?
- 只能在main方法编写测试代码,去调用其他方法进行测试
- 无法实现自动化测试。一个方法测试失效,可能影响其他方法的测试
- 无法得到测试的报告,需要程序员自己去观察测试是否成功
- Junit单元测试框架
- 可以用对方进行测试,他是第三方公司开源出来的(很多开发工具已经集成了Junit框架,比如IDEA)
- 优点
- 可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立
- 不需要程序员去分析测试的结果,会自动生成测试报告出来
- 具体步骤:
- 将Junit框架的jar包导入到项目中(注意:IDEA继承了Junit框架,不需要我们自己手工导入了)
- 为需要测试的业务类,定义对应的测试类,并未每个业务方法,编写对应的测试方法(必须:公共、无参、无返回值)
- 测试方法上必须声明
@Test注解,然后在测试方法中,编写代码调用被测试的业务方法进行测试 - 开始测试:选中测试方法,右键选择“Junit运行”,如果测试通过则是绿色;如果测试失败,则是红色
- Junit断言机制:
Assert.assertEquals(String message, long expected, long actual);- 程序员可以通过该方法预测业务方法的结果
Junit框架的常见注解
Junit单元测试框架的常见注解(Junit 4.xxxx版本)
注释 说明 @Test测试类中的方法必须用它修饰才能成为测试方法,才能启动执行 @Before用来修饰一个实例方法,该方法会在每一个测试方法执行前执行一次 @After用来修饰一个实例方法,该方法会在每一个测试方法执行后执行一次 @BeforeClass用来修饰一个静态方法,该方法会在所有测试方法执行前只执行一次 @AfterClass用来修饰一个静态方法,该方法会在所有测试方法执行后只执行一次 - 在测试方法执行前执行的方法,常用于初始化资源
- 在测试方法执行完后再执行的方法,常用于:释放资源
Junit单元测试框架的常见注解(Junit 5.xxxx版本)
注释 说明 @Test测试类中的方法必须用它修饰才能成为测试方法,才能启动执行 @BeforeEach用来修饰一个实例方法,该方法会在每一个测试方法执行前执行一次 @AfterEach用来修饰一个实例方法,该方法会在每一个测试方法执行后执行一次 @BeforeAll用来修饰一个静态方法,该方法会在所有测试方法执行前只执行一次 @AfterAll用来修饰一个静态方法,该方法会在所有测试方法执行后只执行一次 - 在测试方法执行前执行的方法,常用于初始化资源
- 在测试方法执行完后再执行的方法,常用于:释放资源
反射 (Reflection)
认识反射、获取类
- 反射:反射就是加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造方法等)
- 反射学什么:学习获取类的信息、操作他们
- 反射第一步:加载类,获取类的字节码:Class对象
- 获取类的构造器:Constructor对象
- 获取类的成员方法:Field对象
- 获取类的成员方法:Method对象
- 获取Class对象的三种方式:
Class c1 = 类名.class- 调用Class提供的方法:
public static Class forName(String packet) - Object提供的方法:
public Class getClass(); Class c3 = 对象.getClass();
获取类的构造器
Class提供了从类中获取构造器的方法。
方法名称 说明 Constructor<?>[] getConstructors()获取全部构造器(只能获取public修饰) Constructor<?>[] getDeclaredConstructors()获取全部构造器(只要存在就能拿到) Constructor<?> getConstructor(Class<?>... parameterTypes)获取某个构造器(只能获取public修饰) Constructor<?> getDeclaredConstructor(Class<?>... parameterTypes)获取全部构造器(只要存在就能拿到) 获取类的构造器的作用:依然是初始化对象返回
Constructor提供的方法 说明 T newInstance(Object... initargs)调用此构造器对象表示构造器,并传入参数,完成对象的初始化并返回 public void setAccessible(boolean flag)设置为true,表示禁止检查访问控制(暴力反射)
获取类的成员变量
Class提供了从类中获取成员变量的方法
方法名称 说明 public Field[] getFields()获取类的全部成员变量(只能获取public修饰) public Field[] getDeclaredFields()获取类的全部成员变量(只要存在就能拿到) public Field getField(String name)获取类的某个成员变量(只能获取public修饰) public Field getDeclaredField(String name)获取类的某个成员变量(只要存在就能拿到) 获取到成员变量作用:依然是赋值、取值
方法名称 说明 void set(Object obj, Object value)赋值 Object get(Object obj)取值 public void setAccessible(boolean flag)设置true,表示禁止检查访问权限(暴力反射)
获取类的成员方法
Class提供了从类中获取成员方法的API
方法名称 说明 Method[] getMethods()获取类的全部成员方法(只能获取public修饰) Method[] getDeclaredMethods()获取类的全部成员方法(只要存在就能拿到) Method getMethod(String name, Class<?>... parameterType)获取类的某个成员方法(只能获取public修饰) Method getDeclaredMethod(String name, Class<?>... parameterType)获取类的某个成员方法(只要存在就能拿到) 获取成员方法的作用:依然是执行
Method提供的方法 说明 public Object invoke(Object obj, Object... args)触发某个对象的该方法执行 public void setAccessible(boolean flag)设置true,表示禁止检查访问权限(暴力反射)
作用、应用场景
- 反射的作用:
- 基本作用:可以得到一个类的全部成分然后操作
- 可以破坏封装性
- 最重要的用途:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能
注解
概述、自定义注解
注解(Annotation)
- 就是Java代码里的特殊标记,比如:
Override、Test等,作用是:让其他程序根据注解信息来决定怎么执行该程序 - 注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上等位置处
- 就是Java代码里的特殊标记,比如:
自定义注解
就是自己定义注解
1
2
3public 注解名称 {
public 属性名称 属性名() default 默认值 ;
}
特殊属性名:value
- 如果注解中只有一个value属性,使用注解时,value名称可以不写
注解的原理:
- 本质是一个接口,继承了
Annotation接口 @注解(...),相当于创建一个实现类对象,实现了该接口
- 本质是一个接口,继承了
元注解
元注解:修饰注解的注解
1
2
3
4// 元注解
public Test {
}常见的元注解
@Target@Retention
@Target({ElementType.METHOD}):声明被修饰的注解只能在哪些位置使用Type:类,接口FIELD:成员变量METHOD:成员方法PARAMETER:方法参数CONSTRUCTOR:构造器LOCAL_VARIABLE:局部变量
@Retention(RetentionPolicy.RUNTIME):声明注解的保留周期SOURCE:只作用在源码阶段,字节码文件中不存在CLASS(默认值):保留到字节码文件阶段,运行阶段不存在RUNTIME(开发常用):一直保留到运行阶段
注解的解析
什么是注解的解析:
- 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来
如何解析注解:
指导思想:要解析谁上面的注解,就应该先拿到谁
比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解。
比如要解析成员方法上的注解,则应该获取到成员方法的
Method对象,再通过Method对象解析其上面的注解。Class、Method、Field、Constructor都实现了AnnotatedElement接口,他们都拥有解析注解的能力AnnotatedElement接口提供了解析注释的方法方法名称 说明 public Annotation[] getDeclaredAnnotations()获取当前对象上面的注解 public T getDeclaredAnnotation(Class<T> annotationClass)获取指定的注解对象 public boolean isAnnotationPresent(Class<T> annotationClass)判断当前对象是否存在某个注解
应用场景
- 结合反射等技术做框架
动态代理
程序为什么需要代理?代理长什么样?
- 对象如果嫌身上干的事太多的话,可以通过代理来转移部分职责
- 对象有什么方法想被代理,代理就一定要有对应的方法
如何为Java对象创建一个代理对象?
java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:1
2
3
4public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
// 参数一:用于指定用哪个类加载器,去加载生成的代理类
// 参数二:指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
// 参数三:用来指定生成的代理对象要干些什么