黑马程序员技术交流社区

标题: day14笔记 [打印本页]

作者: 海贼王和皮卡丘    时间: 2018-12-2 15:40
标题: day14笔记
JUnit单元测试
反射
注解
JUnit单元测试
        测试分类
        1,黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值
        2.白盒测试:需要写代码,关注程序具体的执行流程(比如今天学习的JUnit)
集成测试(多个人,多个模块)
接口测试(网络请求的接口)
单元测试(测试每个定义的方法)
JUnit使用步骤:
        1. 定义一个测试类(也叫测试用例)
            包名:xxx.xxx.xx.test
                被测试的类名:   Calculator   
                对应的测试类名: CalculatorTest
        2. 定义测试方法:可以独立运行
                被测试的方法名:       add()      
        对应的测试方法名: testAdd()  
                    建议测试方法的返回值是void, 参数列表是空参
        3. 在方法上加 @Test 注解
        4. 在 @Test 注解上按 Alt+Enter, 选择 "Add 'JUnit4' to Classpath" 导入JUnit依赖环境
        5. 在方法名上右键, 选择 "Run '方法名()'"
            
判定结果:
        红色:失败
        绿色:成功.(测试通过)
       
断言: Assert
        使用断言操作来判断结果是否符合预期:


                Assert.assertEquals(期望的结果, 运算的结果);


                如果 期望的结果 和 运算的结果 相等, 则认为测试通过, 否则测试失败
       
测试失败的原因提示:
    java.lang.AssertionError:
    Expected :1    (表示我期望得到的是1)
    Actual   :-1   (但是实际得到的是-1)
初始化方法:@Before
        用于资源申请,所有测试方法在执行之前都会先执行该方法
释放资源:@After
        修饰方法会在测试方法执行之后会被执行
反射:框架设计的灵魂
Java代码在计算机中的3个阶段:
        SOURCE:源代码阶段
        CLASS:类对象阶段
        RUNTIME:运行时阶段
        *框架:半成品软件.可以在框架的基础上进行软件开发,简化编码
        *反射:将类的各个部分封装为其他对象,这就是反射机制
        好处:
        1.可以在程序的运行中,操作这些对象
        2.可以解耦,提高程序的可扩展性
反射:获取(Class对象)字节码对象的3种方式:
        1.Class.forName(全类名):将字节码加载进内存,返回Class对象
        2.类名.class通过类名的属性class获取
        3.对象.getClass():getClass()方法在Object类中定义着
        结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方法获取的Class对象都是同一个
获取一个类的字节码对象的3种方式:
        1. Class.forName("全类名")
        2. 类名.class                         .
        3. 对象.getClass()


java.lang.Class<T>类: 表示一个类的字节码对象, 其中包含该类中定义的内容
// 获取功能
// 1. 获取成员变量们
        Field[] getFields(): 获取所有 public 的成员变量
        Field getField(String name): 获取指定名称的 public 的成员变量
        Field[] getDeclaredFields(): 获取所有的成员变量, 不考虑权限修饰符
        Field getDeclaredField(String name): 获取指定名称的成员变量, 不考虑权限修饰符
// 2. 获取构造方法们
        Constructor<?>[] getConstructors(): 获取所有 public 的构造方法
        Constructor<T> getConstructor(Class<?>... parameterTypes): 获取指定的 public 构造方法
        Constructor<?>[] getDeclaredConstructors(): 获取所有的构造方法, 不考虑权限修饰符
        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 获取指定的构造方法, 不考虑权限修饰符
// 3. 获取成员方法们:
        Method[] getMethods(): 获取所有 public 的成员方法
        Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的 public 成员方法
        Method[] getDeclaredMethods(): 获取所有的成员方法, 不考虑权限修饰符
        Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取指定的成员方法, 不考虑权限修饰符
// 4. 获取Class对象代表的类的全类名
        String getName(): 获取当前Class对象代表的类的全类名
// 其他
        T newInstance(): 使用当前类的空参构造创建一个对象
        A getAnnotation(Class<A> annotationClass): 获取当前类的注解对象
        ClassLoader getClassLoader(): 返回该类的类加载器
               
java.lang.reflect.Field: 表示一个成员变量
        // 成员方法
        void set(Object obj, Object value): 设置指定对象的成员变量的值
        Object get(Object obj): 获取指定对象的成员变量的值
        void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射
       
java.lang.reflect.Constructor<T>: 表示一个构造方法
        // 成员方法
        T newInstance(Object... initargs): 使用当前构造方法传入参数, 创建对象
        void setAccessible(boolean flag): 注意: 构造方法不能利用此方法忽略权限, 会抛异常
       
java.lang.reflect.Method类: 表示一个成员方法
        // 成员方法
        Object invoke(Object obj, Object... args): 使用指定对象和指定参数值调用此方法
        String getName(): 获取方法名
        void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射
       
java.lang.ClassLoader: 类加载器
        // 成员方法
        InputStream getResourceAsStream(String name): 读取相对于bin目录中的文件, 返回一个字节流
       
常用元注解:
        @Target: 描述注解能够作用的位置
                ElementType枚举的常用取值:
                        TYPE:可以作用于类上
                        METHOD:可以作用于方法上
                        FIELD:可以作用于成员变量上
                示例: @Target(value = {ElementType.TYPE, ElementType.METHOD})
        @Retention: 描述注解被保留的阶段
                RetentionPolicy枚举的取值:
                        SOURCE: 保留到源代码阶段
                        CLASS: 保留到类对象阶段
                        RUNTIME: 保留到运行时阶段
                示例: @Retention(RetentionPolicy.RUNTIME):保留注解到class字节码文件中并被JVM读取到
        @Documented: 加上后, 当前注解会被抽取到api文档中
        @Inherited: 加上后, 当前注解会被子类继承
java.lang.Class<T>
        // 成员方法
        ClassLoader getClassLoader(): 返回该类的类加载器
       
java.lang.ClassLoader: 类加载器 加载.class文件到内存的方法区中, 其他类型文件.properties
        // 成员方法
        InputStream getResourceAsStream(String name): 读取相对于 out/production/模块名 目录中的文件, 返回一个字节流


       
使用类加载器加载配置文件
        // 随便获取一个类的字节码对象
        Class clazz = 类名.class;
        // 用字节码对象获取类加载器, 可加载bin目录中编译的文件
        ClassLoader classLoader = clazz.getClassLoader();
        // 使用类加载器加载一个文件, 返回一个字节流
        InputStream is = classLoader.getResourceAsStream("相对于src目录的相对路径");
        // 有了字节流, 就可以使用Properties的load(InputStream in)方法读取配置
        Properties p = new Properties();
        p.load(is);
        String value = p.getProperty("key");
自定义注解格式:关键字 @interface


    元注解
    public @interface 注解名称 {
        属性; (接口中的抽象方法)
            属性;
            属性;
            ...
    }


@注解名称
属性:
        接口中的"抽象方法"
   
属性的要求:
    1. 属性的"返回值类型"可以是以下类型:
        基本数据类型(8种)
        String
        枚举
        注解
        以上类型的数组
    2. 定义了属性,在使用注解时, 需要"给属性赋值" (其实是抽象方法的返回值)
        1. 属性使用 default 关键字指定默认值, 则可以不赋值
        2. 如果只有一个名为"value"的属性需要赋值, 则 value 可以省略, 直接写值即可
        3. 给数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
元注解:
        用于描述注解的注解
       
常用元注解:
        @Target: 描述注解能够作用的位置
                ElementType枚举的常用取值:
                        TYPE:可以作用于类上
                        METHOD:可以作用于方法上
                        FIELD:可以作用于成员变量上
                示例: @Target(value = {ElementType.TYPE, ElementType.METHOD})
        @Retention: 描述注解被保留的阶段
                RetentionPolicy枚举的取值:
                        SOURCE: 保留到源代码阶段
                        CLASS: 保留到类对象阶段
                        RUNTIME: 保留到运行时阶段
                示例: @Retention(RetentionPolicy.RUNTIME):保留注解到class字节码文件中并被JVM读取到
        @Documented: 加上后, 当前注解会被抽取到api文档中
        @Inherited: 加上后, 当前注解会被子类继承
获取注解属性值的步骤:
        1. 获取注解定义位置的对象 (Class对象(类注解), Field对象(成员变量注解), Method对象(方法注解))
        2. 调用 ProAnno a = cls.getAnnotation(ProAnno.class) 方法获取注解对象
        3. 通过注解对象调用抽象方法获取属性值
       
        // 比如获取一个类上的注解
    注解类型 注解变量名 = 被注解的类.class.getAnnotation(注解名.class);
    数据类型 变量名 = 注解变量名.抽象方法();


    ProAnno proAnno = Test.class.getAnnotation(ProAnno.class);
    String className = proAnno.className();
    String methodName = proAnno.methodName();






       







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2