Junit单元测试
-
测试分类
- 黑盒测试:看不到里面,只能通过输入输出判断错误,一般都是穷举
- 白盒测试:看得到里面,通过逻辑结构来判断错误,耗费较高,一般进行的是单元测试
-
Junit使用:白盒测试
- 步骤
- 定义一个测试类
- 被测试的类名最好写成Test CalculatorTest
- 包名:xxx.xxx.xx.test cn.it.test
- 定义测试方法:可以独立运行
- 方法名:test+方法名 testAdd()
- 返回值:void
- 参数列表:列表
- 给方法加@Test
- 导入junit的依赖
- 一般输出并不能知道结果是否正确,只会报错,所以这时使用断言Assert.assertEquals(预期结果,得到结果);
- 定义一个测试类
- 步骤
package 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 junit;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CalculatorTest {
@Before
public void init(){
System.out.println("init......");
}
@After//即使中间的方法出现异常,也会被执行,所以一般用于资源的释放
public void close(){
System.out.println("close......");
}
//需要引入junit(ALT+ENTER)
@Test
public void testAdd(){
Calculator c = new Calculator();
System.out.println(c.add(1,2));
//断言
Assert.assertEquals(1,c.add(1,2));
}
}
反射
框架:半成品软件。可以在框架的基础上进行软件开发,简化代码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
Java代码在计算机中先进行Javac编译成class文件(source阶段),通过类加载器变成类对象(class类对象阶段),然后被创建对象使用(Runtime运行阶段)
-
获取class对象(获取字节码对象,对应三个阶段)
-
Class.forname(“全类名”);
- 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
-
类名.class
- 多用于参数的传递
-
对象.getclass()
- 多用于对象的获取字节码的方式
-
-
同一个字节码文件(*.class)在一次程序的运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。
-
Class对象功能
- 获取功能
- 获取成员变量们
- 获取构造方法们
- 获取成员变量们
- 获取类名
- 获取功能
-
案例
pro.properties
className = it.Person
methodName = eat
Test.java
package it;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test {
public static void main(String[] args) throws Exception {
//1加载配置文件
//1.1创建Properties对象
Properties properties = new Properties();
//1.2加载配置文件,转换为一个集合
//1.2.1获取class目录下的配置文件
ClassLoader classLoader = Test.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
properties.load(is);
//2.获取配置文件定义的资源
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
//3.加载该类进内存,
Class cls = Class.forName(className);
//4.创建对象
Object o = cls.newInstance();
//5.获取方法
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(o);
}
}
Person.java
package it;
public class Person {
private String a;
protected String b;
public String c;
String d;
public Person() {
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
public void eat(){
System.out.println("eat,,,");
}
@Override
public String toString() {
return "Person{" +
"a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
注解
-
注解:说明程序的,给计算机看的。
-
定义:注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值
注解也就是Annotation,相信不少人也和我之前一样以为和注释和doc一样,是一段辅助性的文字,其实注解不是这样的。
从JDK5开始,java增加了对元数据(描述数据属性的信息)的支持。其实说白就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。
-
作用分类:
- 编写文档:通过代码标识里的元数据生成文档【生成doc文档】
- 代码分析:通过代码标识里的元数据对代码进行分析【使用反射】
- 编译检查:通过代码标识里的元数据让编译器能够实现基本的编译检查【override】
-
自定义注解
元注解 public @interface 注解名{ }
-
本质:
public interface 注解名 extends java.lang.annotation.Annotation { }
-
属性:接口中的抽象方法
- 要求:
- 属性的返回值类型只有下列取值
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型数组
- 定义了属性,在使用时需要给属性赋值
- 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
- 如果只有一个属性需要赋值,并且属性名称为value,则value可以省略,直接定义值即可
- 数组赋值时。使用{}包裹
- 属性的返回值类型只有下列取值
- 要求:
-
元注解:用于描述注解的注解
- @Target:描述注解能够作用的位置
- @Retention:描述注解能够被保留的阶段
- @Documented:描述注解是否能被抽取到api文档
- @Inherited:描述注解是否能被继承
-
案例:
check注解
package it;
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 {
}
Calculator
package it;
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));
}
}
TestCheck
package it;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
public class TestCheck {
public static void main(String[] args) throws IOException {
//1. 创建对象
Calculator c = new Calculator();
//2. 获取字节码文件
Class cls = c.getClass();
//3. 获取所有方法
Method[] methods = cls.getMethods();
int num = 0;
BufferedWriter bw = new BufferedWriter(new FileWriter("BUG.txt"));
for (Method method : methods) {
//判断方法是是否有Check注解
if (method.isAnnotationPresent(Check.class)){//有Check注解就执行
try {
method.invoke(c);
} catch (Exception e) {
num ++;
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("本次测试一共有" + num +"次异常");
bw.flush();
bw.close();
}
}
*注:所有文章都只为自己做笔记*