Junit单元测试
测试概述
黑盒测试
白盒测试
Junit是白盒中的一种
步骤:
1.定义一个测试类(测试用例
建议:
测试类名:被测试的类名Test CalculatorTest
包名:xxx.xxx.test cn.echo233.test
2.定义测试方法:可以独立运行
建议:
方法名:test测试的方法名 testAdd()
返回值:void
参数列表:空参
3.给方法加@Test
4.导入junit依赖环境
判定结果
红色:失败
绿色:成功
一般我们会用断言操作来处理结果
Assert.assertEquals(期望的结果,运算的结果)
补充:
@Before修饰的方法会在测试方法之前被执行
@After修饰的方法会在测试方法之后被执行
@Before
public void init(){
System.out.println("init...");
}
@After
public void close(){
System.out.println("close...");
}
@Test
public void testAdd(){
Calculator calculator = new Calculator();
int add = calculator.sub(3, 6);
Assert.assertEquals(9,add);
}
@Test
public void testSub(){
System.out.println("减法执行了...");
}
反射:框架设计的灵魂
框架:半成品软件,可以在框架的基础上进行软件的开发,简化代码
反射:将类的各个组成部分封装成其他对象
好处:1.可以在程序运行的过程中,操作这些对象
2.可以解耦,提高程序的可扩展性
获取class文件的三种方式
Class cls1 = Class.forName("cn.echo233.reflect.Person");
System.out.println(cls1);
Class<Person> cls2 = Person.class;
System.out.println(cls2);
Class cls3 = new Person().getClass();
System.out.println(cls3);
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true
class对象的功能
获取功能
获取成员变量们
Field[] getFields():获取所有public修饰的成员变量
Field getField(String name)获取指定名称的public修饰的成员变量
Field[] getDeclaredFields()获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)
获取构造方法们
Constructor<?>[] getConstructors()
Constructor getConstructor(Class<?>… parameterTypes)
Constructor getDeclaredConstructor(Class<?>… parameterTypes)
Constructor<?>[] getDeclaredConstructors()
获取成员方法们
Method[] getMethods()
Method getMethod(String name, Class<?>… parameterTypes)
Method getDeclaredMethod(String name, Class<?>… parameterTypes)
Method[] getDeclaredMethods()
获取类名
String getName()
Class<Person> personClass = Person.class;
Method method = personClass.getMethod("eat",String.class);
Person person = new Person("liu",26);
method.invoke(person,"饭");
System.out.println(method.getName());
System.out.println(personClass.getName());
具体的反射使用案例
public class ReflectTest {
public static void main(String[] args) throws Exception {
//加载配置文件
//创建Properties对象
Properties properties = new Properties();
ClassLoader classLoader = ReflectTest.class.getClassLoader();
//加载配置文件,转换为一个集合
//获取class目录下的配置文件
InputStream is = classLoader.getResourceAsStream("cn/echo233/reflect/prop.properties");
properties.load(is);
//获取配置文件中定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
//加载该类进内存
Class cls = Class.forName(className);
//创建对象
Object obj = cls.newInstance();
Method method = cls.getMethod(methodName,String.class);
method.invoke(obj,"饭");
}
}
注解
概念
注解:说明程序的,给计算机看的
注释:说明程序的,给程序员看的
作用分类:
1.编写文档:生成doc文档
【重】2.代码分析:对代码进行分析(反射)
3.编译检查:编译检查
jdk内置注解
@override
@Deprecated
@SuppressWarnings压制警告
一般传递参数all(@SuppressWarnings(“all”)
自定义注解
格式:(两条)
元注解
public @interface 注解名称{}
本质(javap xxx.class指令进行反编译)
注解本质是一个接口,该接口默认继承Annotation接口
public interface xx extends java.lang.annotation.Annotation {}
属性:接口中可以定义的成员方法(抽象方法)
1.属性的返回值类型
基本数据类型
String
枚举
注解
以上类型的数组
2.定义了属性,在使用时需要给属性赋值
1.default
2.value
3.数组{}
元注解:用于描述注解的注解
@Target:描述注解能够作用的位置
ElementType取值(这是枚举类型)
TYPE类
METHOD方法
FIELD成员变量
@Retention:描述注解被保留的阶段
@Retention(RetentionPolicy.RUNTIME)当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
@Documented:描述注解是否会被抽取到api文档中
@Inherited:描述注解是否会被子类继承
在程序中使用注解
/**
* 描述需要执行的类名,方法名
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
String className();
String methodName();
}
@Pro(className = "cn.echo233.Student",methodName = "show")
public class ReflectTest {
public static void main(String[] args) throws Exception {
//解析注解
//获取该类的字节码文件对象
Class<ReflectTest> reflectTestClass = ReflectTest.class;
//获取上边的注解对象
//其实就是在内存中生成了一个该注解接口的子类实现对象
Pro annotation = reflectTestClass.getAnnotation(Pro.class);
String className = annotation.className();
String methodName = annotation.methodName();
//加载该类进内存
Class cls = Class.forName(className);
//创建对象
Object obj = cls.newInstance();
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
}
小结:
1.常是使用注解
2.注解给谁用?
1.编译器
2.给解析程序用
3.注解不是程序的一部分,可以理解注解是一个标签(方法还是方法,类还是类)
Demo
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
public class Calculator {
@Check
public void add(){
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...");
}
}
public class TestCheck {
public static void main(String[] args) throws IOException {
Calculator calculator = new Calculator();
Class<Calculator> calculatorClass = Calculator.class;
Check annotation = calculatorClass.getAnnotation(Check.class);
Method[] methods = calculatorClass.getDeclaredMethods();
int count = 0;
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
for (Method method : methods) {
if (method.isAnnotationPresent(Check.class)) {
try {
method.invoke(calculator);
} catch (Exception e) {
count++;
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("一次"+count+"次出bug了");
bw.flush();
bw.close();
}
}