单元测试&反射&注解

本文详细介绍了如何在Java中使用Junit进行单元测试,包括测试方法的组织、Junit注解的运用,以及反射机制的深入学习,如获取和使用类的构造器、成员变量和方法。同时提及了元注解和注解解析的应用实例。
摘要由CSDN通过智能技术生成

单元测试

         就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。

咱们之前是如何进行单元测试的?有啥问题 ? 

 

Junit单元测试框架 

          可以用来对方法进行测试,它是由Junit公司开源出来的 

具体步骤 

 Junit框架的常见注解

public class StringUtilTest {

    @Test
    @Before
    public void testPrintNumber(){

        StringUtil.printNumber("哈哈");
        StringUtil.printNumber(null);
    }

    @Test
    public void testGetMaxIndex(){

        int sum = new StringUtil().getMaxIndex("蝙蝠侠不打你了");
        System.out.println(sum);

        Assert.assertEquals("警告,警告",6,sum);
    }

    @Test
    @After
    public void testPrint(){

        System.err.println("结束");
    }
}

 反射(Reflection)

          反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。 

                                              

反射学什么? 

 

获取Class对象的三种方式 

1.直接使用类名.class获取:Class c1 = 类名.class

2.调用Class提供的方法:Class c2 = Class.forName("全类名")

3.调用Object提供的方法:Class c3 = 对象.getClass() 

public class Demo1 {

    @Test
   public void testDemo01() throws ClassNotFoundException {
       Class catClass = Cat.class;
       System.out.println(catClass.getName());

       Class aClass = Class.forName("com.itheima.b_反射.Cat");
       System.out.println(aClass);

       Class aClass1 = new Cat().getClass();
       System.out.println(aClass1);
   }
}

 获取类的构造器

 

/*
获取构造器[下面是Class的方法]
    Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
    Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
    Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)

使用构造器(创建对象)[下面是Constructor的方法]
    T newInstance(Object... initArgs)	调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {

    @Test
    public void testConstructor() throws NoSuchMethodException {

        Class<Cat> clazz = Cat.class;

        //获取全部构造器(public)
        Constructor[] constructors = clazz.getConstructors();

        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        System.out.println("====================================");

        Constructor<Cat> constructor = clazz.getConstructor();
        System.out.println(constructor);
        System.out.println("===============================");
        Constructor<Cat> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println("方法名:" + declaredConstructor.getName() + "参数个数:"+ declaredConstructor.getParameterCount());
    }

    @Test
    public void testNew() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class calazz = Cat.class;

        Constructor declaredConstructor = calazz.getDeclaredConstructor(String.class, int.class);

        declaredConstructor.setAccessible(true);

        Cat 加菲猫 = (Cat)declaredConstructor.newInstance("加菲猫", 3);

        System.out.println(加菲猫);
    }
}

 获取类的成员变量

 

public class Demo3 {

   @Test
    public void testField() throws NoSuchFieldException {

       Class<Cat> catClass = Cat.class;

       //获取类的所有公共成员变量(只能获取public修饰的)
       Field[] fields = catClass.getFields();
       for (Field field : fields) {
           System.out.println(field);
       }

       System.out.println("===============");
       //获取类的全部成员变量
       Field[] declaredFields = catClass.getDeclaredFields();
       for (Field declaredField : declaredFields) {
           System.out.println(declaredField.getName() + declaredField.getType());
       }
       System.out.println("====================");
       Field a = catClass.getField("a");//获取某个类的成员变量,只要存在就能拿到
       System.out.println(a);

       Field age = catClass.getDeclaredField("age");
       System.out.println(age);
   }

   @Test
   public void test2() throws NoSuchFieldException, IllegalAccessException {

       Class clazz = Cat.class;

       Cat cat = new Cat();
      // System.out.println(cat);

       Field age = clazz.getDeclaredField("age");

       Field name = clazz.getDeclaredField("name");
       //暴力反射
       age.setAccessible(true);
       name.setAccessible(true);

       age.set(cat,5);
       name.set(cat,"哈哈");
       System.out.println(cat);

       //取值
       Object o = age.get(cat);
       System.out.println(o);
   }
}

 获取类的成员方法

 

 

/*
获取成员方法[Class提供]
    Method[] getMethods()	获取类的全部公共成员方法(只能获取public修饰的)
    Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name, Class<?>... parameterTypes) 	获取类的某个公共成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name, Class<?>... parameterTypes)	获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
    public Object invoke(Object obj, Object... args)	触发某个对象的该方法执行。
    public void  setAccessible(boolean flag)	设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {

    @Test
    public void testMethods() throws NoSuchMethodException {
        Class<Cat> catClass = Cat.class;

        Method[] methods = catClass.getMethods();
        for (Method method : methods) {
            System.out.println("方法名:"+ method.getName() + "返回值类型:" + method.getReturnType());
        }

        System.out.println("===========================");

        Method[] declaredMethods = catClass.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            System.out.println("方法名:"+ declaredMethod.getName() + "返回值类型" + declaredMethod.getReturnType());
        }

        System.out.println("===========================");
        Method eat = catClass.getDeclaredMethod("eat");
        System.out.println("方法名:"+ eat.getName() + "返回值类型" + eat.getReturnType());

        System.out.println("===========================");
        Method eat1 = catClass.getDeclaredMethod("eat", String.class);
        System.out.println("方法名:"+ eat1.getName() + "返回值类型" + eat1.getReturnType());
    }

    @Test
    public void tese2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        Class<Cat> clazz = Cat.class;

        Method eat = clazz.getDeclaredMethod("eat", String.class);

        eat.setAccessible(true);

        Cat cat = new Cat();
        Object invoke = eat.invoke(cat, "🐟");
        System.out.println(invoke);
    }
}

案例: 

/*
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台

*/
public class Demo5 {
    public static void main(String[] args) {
        //1. 准备两个对象
        Student student = new Student("柳岩", 40, '女', 167.5, "女星");
        Teacher teacher = new Teacher("播妞", 6000);

        //2.调用方法

        print(student);
    }

    public static void print(Object o)  {

        try {
            Class clazz = o.getClass();

            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {

                declaredField.setAccessible(true);

                String name = declaredField.getName();
                Object o1 = declaredField.get(o);
                System.out.println(name+o1);
            }
        }catch (Exception e){
        }

    }
}



class Student{
    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;
}

class Teacher {
    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    private String name;
    private double salary;
}

反射的作用 

 

注解

元注解

            指的是:修饰注解的注解。 

 注解解析器

     就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。 

如何解析注解 

 

 

public class ClassNameCheckParser {

    public static void checkClassName(){
        //1.存放不符合规范的类
        ArrayList<String> list = new ArrayList<>();

        //2.获取指定包下的所有类
        Set<Class> clazzSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //3.遍历set集合找到标注@ClassNameCheck注解的类'

        for (Class clazz : clazzSet) {

            //判断某个类上是否有某个注解
            if(clazz.isAnnotationPresent(ClassNameCheck.class)){

                //获得类名
                String simpleName = clazz.getSimpleName();
                //检查类名是否以Heima开头
                if(!simpleName.startsWith("Hei")){

                    list.add(simpleName);
                }
            }
        }

        //判断集合中是否有不符合规范的,如果有直接保存
        if(list.size() > 0) {

            System.out.println("下面类名不符合规范");
            for (String name : list) {
                System.out.println(name);
            }
            throw new RuntimeException("程序终止");
        }

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值