Junit单元测试
-
测试分类:
1.黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
2.白盒测试:需要写代码,并且需要关注具体的执行流程
-
Junit的使用:白盒测试:
-
步骤
1.定义一个测试类(测试用例)
- 建议:
- 测试包名:被测试的类名Test 例如:CalculatorTest
- 包名:xxx.xxx.xxx.test cn.itcast.test
2.定义测试方法类:可以独立运行
-
建议
- 方法名:test测试类名 testAdd()
- 返回值:void
- 参数列表:空参
3.给方法加@Test
4.导入junit依赖环境
-
判定结果:
-
红色:失败
-
绿色:成功
-
一般我们会使用断言操作处理结果
- Assert.assertEquals(期望的结果,实际的结果);
-
- 建议:
-
代码测试
Calculator类
package cn.itcast.junit;
/*
* 计算器类
* */
public class Calculator {
/**
* 加法
*
* @param a
* @param b
* @return
*/
public int add(int a, int b) {
return a - b;//此处本应该为加号,现在用作测试为后面报错作铺垫
}
/**
* 减法
*
* @param a
* @param b
* @return
*/
public int sub(int a, int b) {
return a - b;
}
}
CalculatorTest类(里面需要写注解@Test 然后导入junit包)
package cn.itcast.test;
import cn.itcast.junit.Calculator;
import org.junit.Assert;
import org.junit.Test;
public class CalculatorTest {
/**
* 测试add方法
*/
@Test
public void testAdd(){
System.out.println("我被输入来了");
//1.创建计算器对象
Calculator c = new Calculator();
//2.调用add方法
System.out.println(c.add(1,2));
//如果正常运行则是绿色,否则为红色
//3.断言 我断言这个结果为3
Assert.assertEquals(3,c.add(1,2));
}
}
展示结果:
补充:
- @Before:
- 修饰的方法会在测试方法之前被自动执行
- @After:
- 修饰的方法会在测试方法之后被自动执行
代码示例:
/**
* 初始化方法
* 用于资源的申请,所有测试方法再执行之前都会先执行该方法
*/
@Before
public void init(){
System.out.println("init...");
}
/**
* 释放资源的方法
* 在所有测试方法执行完毕之后,都会自动执行该方法,不管有没有报错
*/
@After
public void close(){
System.out.println("close...");
}
测试结果:
反射:框架设计的灵魂
类从源文件加载到内存再到运行时阶段的展示图:
-
框架:半成品软件,可以在框架的基础上进行软件开发,简化编码
-
反射:将类的各个组成部分封装为其他对象,这就是反射机制
- 好处:
- 可以在程序运行过程中,操作这些对象。
- 可以解耦,提高程序的可扩展性。
- 好处:
-
获取class对象的方式:
1.class.forName(“全类名”):将字节码文件加载进内存,返回class对象
* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2.类名.class::通过类名的属性class获取
*多用于参数的传递
3.对象.getClass():getClass()方法在Object类中定义着。
* 多用于对象获取字节码的方式
-
结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的Class对象都是同一个
-
代码示例:
/*
获取class对象的方式:
1.class.forName("全类名"):将字节码文件加载进内存,返回class对象
2.类名.class::通过类名的属性class获取
3.对象.getClass():getClass()方法在Object类中定义着。
*/
//1.Class.forName("全类名")
Class cls = Class.forName("cn.itcast.domain.Person");
System.out.println(cls);
//2.导入想要获取的类的字节码文件的包中的类;
Class pc= Person.class;
System.out.println(pc);
//3.new一个对象,通过对像的getClass方法来获取字节码文件。
Person person = new Person();
System.out.println(person.getClass());
效果展示:![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/70e343aa6261c1315c7fab9349c58515.png)
-
Class对象功能:
- 获取功能:
1.获取成员变量们
-
Field[] getFields() --------- 获取public修饰的成员变量
-
Field[] getField(String name) -----获取指定名称的public修饰的成员变量
-
Field[] getDeclaredFields() -------获取所有的成员变量,不考虑修饰符
-
Field[] getDeclaredField(String name) ------获取单个的成员变量,不考虑修饰符
2.获取构造方法们
-
Constructor <?> [ ] getConstructors ( )
-
Constructor getConstructor (类<?>. . . parameterTypes)
-
Constructor <?> [ ] getDeclaredConstructors ( )
-
Constructor getDeclaredConstructor (类<?>. . . parameterTypes)
3.获取成员方法们:
-
Method [] getMethods()
-
Method getMethod(String name, 类<?>… parameterTypes)
-
Method[] getDeclaredMethods()
-
Method getDeclaredMethod(String name, 类<?>… parameterTypes)
4.获取类名
String getName() -
-
Filed :成员变量
- 操作:
- 1.设置值
- set(Object obj, Object value)
- 2.获取值
- get(Object obj)
- 3.忽略访问权限修饰符的安全检查
- setAccessablie(true):暴力反射
- 1.设置值
- 操作:
代码示例:
=ReflectDemo02.java文件===
package cn.itcast.reflect;
import cn.itcast.domain.Person;
import java.lang.reflect.Field;
public class ReflectDemo02 {
/*
Class对象功能:
获取功能:
1.获取成员变量们
* Field[] getFields()
* Field[] getField(String name)
* Field[] getDeclaredFields()
* Field[] getDeclaredField(String name)
2.获取构造方法们
* Constructor <?> [ ] getConstructors ( )
* Constructor<T> getConstructor (类<?>. . . parameterTypes)
* Constructor <?> [ ] getDeclaredConstructors ( )
* Constructor<T> getDeclaredConstructor (类<?>. . . parameterTypes)
3.获取成员方法们:
* Method [] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4.获取类名
* String getName()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class personClass = Person.class;
/*
1.获取成员变量们
* Field[] getFields() -----获取所有public修饰的成员变量
* Field[] getField(String name) -----获取指定的public修饰的成员变量
* Field[] getDeclaredFields()
* Field[] getDeclaredField(String name)
*/
//1.Field[] getFields() 获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-------------------");
//2.Field[] getField(String name) -----获取指定的public修饰的成员变量
Field a = personClass.getField("a");
//获取成员变量a 的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//设置a的值
a.set(p,"张三啊啊啊啊");
System.out.println(p);
System.out.println("============ ");
System.out.println("获取所有的成员变量,不考虑修饰符");
// Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//Field[] getDeclaredField(String name) //获取单个的成员变量,不考虑修饰符
System.out.println("获取单个的成员变量,不考虑修饰符");
Field d = personClass.getDeclaredField("d");
//忽略访问权限修饰符的安全检查
d.setAccessible(true); //暴力反射
Object value2 = d.get(p);
System.out.println(value2);
}
}
= = = = = = = = = = Person.java文件 = = = = = = = = = =
package cn.itcast.domain;
public class Person {
private String name;
private int age;
public String a;
public String DD;
protected String b;
String c;
private String d;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
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 + '\'' +
", DD='" + DD + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
效果展示:
Constructor:构造方法
- 创建对象:
- T newInstance(Object… initargs)
- 如果使用空参数构造方法创建对象,操作可以简化为:Class对象的newInstance方法
- constructor.setAccessablite(true):暴力反射
示例代码:
public class ReflectDemo03 {
/*
Class对象功能:
获取功能:
1.获取成员变量们
* Field[] getFields()
* Field[] getField(String name)
* Field[] getDeclaredFields()
* Field[] getDeclaredField(String name)
2.获取构造方法们
* Constructor <?> [ ] getConstructors ( )
* Constructor<T> getConstructor (类<?>. . . parameterTypes)
* Constructor <?> [ ] getDeclaredConstructors ( )
* Constructor<T> getDeclaredConstructor (类<?>. . . parameterTypes)
3.获取成员方法们:
* Method [] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4.获取类名
* String getName()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class personClass = Person.class;
/*
2.获取构造方法们
* Constructor <?> [ ] getConstructors ( )
* Constructor<T> getConstructor (类<?>. . . parameterTypes)
* Constructor <?> [ ] getDeclaredConstructors ( )
* Constructor<T> getDeclaredConstructor (类<?>. . . parameterTypes)
*/
//1. Constructor <?> [ ] getConstructors ( )
//获取字节码文件Person的类的构造器,使用有参构造
Constructor constructors = personClass.getConstructor(String.class,int.class);
System.out.println(constructors);
//使用Contructor中的方法
Object person = constructors.newInstance("张三", 15);
System.out.println(person);
System.out.println("============================");
//使用无参构造
Constructor constructors1 = personClass.getConstructor();
System.out.println(constructors1);
//使用Contructor1中的方法,创建对象
Object person1 = constructors1.newInstance();
System.out.println(person1);
System.out.println("=============");
//使用Class里面的方法创建对象
Object o = personClass.newInstance();
System.out.println(o);
}
}
Method :方法对象
- `执行方法:
- Object invoke(Object obj, Object… args)
- 获取方法名称:
- `String getName:获取方法名。
示例代码:
public class ReflectDemo04 {
/*
Class对象功能:
获取功能:
1.获取成员变量们
* Field[] getFields()
* Field[] getField(String name)
* Field[] getDeclaredFields()
* Field[] getDeclaredField(String name)
2.获取构造方法们
* Constructor <?> [ ] getConstructors ( )
* Constructor<T> getConstructor (类<?>. . . parameterTypes)
* Constructor <?> [ ] getDeclaredConstructors ( )
* Constructor<T> getDeclaredConstructor (类<?>. . . parameterTypes)
3.获取成员方法们:
* Method [] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
4.获取类名
* String getName()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class personClass = Person.class;
/*
* Method [] getMethods()
* Method getMethod(String name, 类<?>... parameterTypes)
* Method[] getDeclaredMethods()
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)
*/
//1.Method getMethod(String name, 类<?>... parameterTypes)
//获取指定名称的方法
Method eat_method = personClass.getMethod("eat");
Person person = new Person();
//执行方法
eat_method.invoke(person);
System.out.println("===============");
Method eat_method2 = personClass.getMethod("eat", String.class);
//执行方法
eat_method2.invoke(person,"好吃的");
System.out.println("=====================");
//查看所有的方法,包含了Object的方法还有类的方法;
// Method [] getMethods()
Method[] methods = personClass.getDeclaredMethods();
for (Method method : methods) {
//打印完整方法
System.out.println(method);
//获取方法名
String name = method.getName();
System.out.println(name);
// method.setAccessible(true);//暴力反射
}
//获取类名:
String className = personClass.getName();
System.out.println(className);
}
}
注解
-
概念:说明程序的,给计算机看的。
-
注释:用文字描述程序,给程序员看的,
-
定义:注解(Annotation),也叫元数据。- 种代码级别的说明。它是JDK1. 5及以后版本引入的一个特性,与类、接口、枚举是在同-一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
-
概念描述:
- JDK 1.5 之后的新特性
- 说明程序的
- 使用注解:@注解名称
-
作用分类:
-
@编写文档:通过代码里标识的注解生成文档[生成文档doc文档]
②代码分析:通过代码里标识的注解对代码进行分析[使用反射]
③编译检查:通过代码里标识的 注解让编译器能够实现基本的编译检查[override] -
JDK中预定义的一些注解
-
@Override :检测被该注解标注的方法是否是继承自父类(接口)的
-
@Deprecated :该注解标注的内容,表示已过时
-
@SuppressWarnings :压制警告
* 一般传递参数all @SuppressWarnings(“all”)
-
-
自定义注解
-
格式:
* 元注解
* public @interface 注解名称{
属性列表;(实际上是成员方法)
}
-
本质:注解本质上就是一个接口,该接口默认继承Annotation接口
-
public interface MyAnno extends java.lang.annotation.Annotation {
} -
属性:接口中的抽象方法
- 要求:
-
1.属性的返回值类型有下列取值
- 基本数据类型(八大基本类型= byte ,short,int ,long,float,double,char,boolean)--------四大引用:数组,类,接口,字符串
- String
- 枚举
- 注解
- 以上类型的数组
-
2.定义了属性,在使用时需要给属性赋值
- 1.如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值
- 2.如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义即可
- 3.数组赋值时,值使用{ }包裹。如果数组中只有一个值,则{ }省略。
-
元注解:
- @Target:描述注解能够作用的位置
- ElementType取值:
- TYPE:可以作用于类上
- METHOD:可以作用于方法上
- FIELD:可以作用于成员变量上
- TYPE:可以作用于类上
- ElementType取值:
- @Retention :描述注解被保留的阶段(源码阶段,class阶段,runtime阶段)
- @Retention(RetentionPolicy.RUNTIME) :当前被表述的注解,会保留到class字节码文件中,并被JVM读取到
- @Target:描述注解能够作用的位置
-
@Documented:描述注解是否被抽取到api文档中
-
@Inherited:描述注解是否被子类继承
-
- 要求:
-
在程序中使用(解析)注解
在程序中使用(解析)注解
-
-
1.获取注解定义的位置的对象,(class,Method,Field)
2.获取指定的注解
getAnnotation(Class)
其实就是在内存中生成了一个该注释的子类实现对象
/*
public class ProImple implements Pro{
public String className(){
return "cn.itcast.annotation.Demo1";
}
public String methodName(){
return "show";
}
*/
3.调用注解中的抽象方法获取配置的属性值
小结
1.以后大多数时候,我们会使用注解,为不是自定义注解
2.注解给谁用?
1.编译器
2.给解析程序用
3.注解不是程序的一部分,可以理解为注解就是一个标签