单元测试 反射 注解

今日内容

单元测试

测试概述

在我们编写代码的时候,开发了很多功能,我们需要对这些已经开发好的功能提前进行测试,检测功能方法是否有漏洞,是否有bug,这个时候我们可以使用Junit单元测试对我们开发的代码进行测试。

Junit是Java语言的单元测试框架,属于第三方的一个工具,一般情况下我们需要导入相应的jar包,对于目前使用的集成开发工具自带的,我们今天是以Idear开发工具为主

Junit属于白盒测试

测试分类

  • 黑盒测试:大多数测试的细节隐藏起来,通常使用的一些软件进行测试

  • 白盒测试:大多数是需要写一些代码进行测试,我们能够看到一些测试的流程。

  • 单元测试 反射 注解_第1张图片

Junit使用

  • 步骤

    1. 下载一个Junit对应的版本jar包

    2. 添加jar依赖到工程里面

    3. 定义一个测试类

      • 建议:

        • 测试类名:被测试的类Test 如:UserTest、PeopleTest、CalculatorTest....

        • 测试类:应该放到测试资源包中

        • 测试包:xxx.xxx.test 如:com.zhiyou100.test.user

      • 定义测试方法:可以实现独立运行 Junit4/Junit5

        • 建议:

          • 方法名:test被测试的功能方法名 如:testGetName()、testAddNum()

          • 返回值:void

          • 参数列表:Junit4中-->空参 Junit5--->可以携带

          • 修饰符:一般Junit4中使用public Junit5中使用范围较广

        •  

      •  

    4. 给方法上添加注解@Test

  • 结果判定

    • 红色--->测试失败,中间可能出现了异常

    • 橘黄色 ---> 测试失败 实际的值和我们期望的值不一致

    • 绿色 --->测试成功

    • 一般情况下,我们都是使用断言(Assert)操作来处理结果的

      示例代码:

      Assert.assertEquals(期望的值,实际的值);
  • Junit的其他测试相关的注解:

    JUnit4中

    • @Test 把一个方法标记为测试方法

    • @Before 每一个测试方法执行前会自动调用一次该方法(搭配@Test一起使用)

    • @After 每一测试方法执行后会自动调用一次该方法(搭配@Test一起使用)

    • @BeforeClass 所有的测试方法执行前执行一次,在测试类还没有进行实例化已经被加载到,标记的方法为静态方法(搭配@Test一起使用)

    • @AfterClass 所有的测试方法执行后执行一次,在测试类还没有进行实例化已经被加载到,标记的方法为静态方法(搭配@Test一起使用)

    • @Ignore 暂不执行该测试方法(待定的) (搭配@Test一起使用)

    Junit5中

    • @Test 把一个方法标记为测试方法

    • @BeforeEach 每一个测试方法执行前会自动调用一次该方法(搭配@Test一起使用)

    • @AfterEach 每一测试方法执行后会自动调用一次该方法(搭配@Test一起使用)

    • @BeforeAll 所有的测试方法执行前执行一次,在测试类还没有进行实例化已经被加载到,标记的方法为静态方法(搭配@Test一起使用)

    • @AfterAll 所有的测试方法执行后执行一次,在测试类还没有进行实例化已经被加载到,标记的方法为静态方法(搭配@Test一起使用)

    • @Disabled 暂不执行该测试方法(待定的) (搭配@Test一起使用)

    • ......

  • 静态导入

    JDK5之后出现的新特性,只要在import后面加上关键字static,就可以把后面类的static修饰的变量和方法导入到本类中。调用的时候和调用本类中的静态成员没有区别。

    • 静态导入格式:import static 包名.类名.静态成员名 ----> import static 包名.类名.*

    • 注意事项:

      • 方法必须是静态的

      • 如果有多个静态方法重名,添加前缀,即添加类名

  • @Test属性操作

    • expected属性 期望测试中携带有异常信息,格式 @Test(expected = NullPointerException.class)

      如果出现异常,测试成功,如果未出现异常,测试失败

    • timeout属性,用来测试方法的执行时间 格式 @Test(timeout=5),单位为毫秒值,如果运行时间在设置值之内,则测试成功,如果超出了设置值范围,则测试失败。

反射

  • 动态语言

    是一类可以在程序运行过程中改变其结构的语言。比如说定义的方法、对象、一些功能代码可以在程序运行中被加载进去,从而达到修改或者删除已有的方法和数据

    动态语言:JavaScript(脚本语言)、PHP 、Python、C#等等

  • 静态语言

    与动态语言相比,运行时程序结构不发生改变的语言就是静态语言。 如C、C++、Java等

    Java虽不是动态语言,但是称之为“准动态语言”,可以利用反射机制来动态的获取类结构信息并且修改类结构信息。Java的动态性使开发更加灵活。

反射概述

  • Reflection,在程序中主要是借助Reflection API获取类结构的内部信息,并且能够直接操作类结构内部信息(属性和方法) 如:Class.forName("com.mysql.jdbc.Driver");// 硬编码

  • 类加载进内存后,在堆存当中就产生了一个Class类型对象(一个类在内存当中有且只有一个Class对象),这个对象就包含了完整的类的结构信息。(属性、方法、构造方法、类名、静态信息等等)。我们可以通过这个对象看到类的内部结构。这个对象就像一面镜子一样。透过这个镜子可以看到类的内部结构。这种形式,我们形象的称之为“反射机制”。

  • 反射一般把它当成框架的灵魂

    框架:半成品软件,我们可以在框架的基础上进行开发,简化代码

  • 好处:

    • 可以在程序运行过程中 ,动态的操作这些对象

    • 可以达到解耦,提高程序的可扩展性。

  • 借助于Class类、Method类、Filed类、Constructor类实现反射

  • 单元测试 反射 注解_第2张图片

单元测试 反射 注解_第3张图片

单元测试 反射 注解_第4张图片

反射常用API操作

获取Class对象:有三种方式

  • Class.forName("类的全路径"):将字节码文件加载进内存当中,返回Class对象

    • 多用于读取配置文件 xml/properties,将类名,方法名,用户名等等配置到文件中

  • 类名.class :通过类名的属性class获取Class对象

    • 多用于参数传递

  • 对象.getClass():通过getClass()方法获取Class对象,getClass() 是Object类中的方法

    • 常用于获取对应的字节码对象

  • 总结:不论是通过哪种方式获取到的,同一个字节码文件在一次程序运行过程中,只会生成一个Class对象

Method对象、Field对象、Constructor对象

属性对象

  • 获取属性对象

    • Field getField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。

    • Field[] getFields() 返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。

    • Field getDeclaredField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。 不限制权限修饰符

    • Field[] getDeclaredFields() 返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。 不限制权限修饰符

  • 设置属性对象值

    void set(Object obj,Object value):第一个参数是对应的实际对象,第二个参数是需要设置的值

  • 获取属性对象值

    Object get(Object obj) : 获取对应的属性值

  • 忽略访问权限修饰符的安全性检查:关闭访问权限

    setAccessiable(boolean flag) 传入true值,关闭访问权限,传入false值,打开访问权限

构造对象

  • 获取构造对象

    • Constructor getConstructor(类... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。

    • Constructor[] getConstructors() 返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。

    • Constructor getDeclaredConstructor(类... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。

    • Constructor[] getDeclaredConstructors() 返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类

  • 构建对象

    T newInstance(Object ... initargs)

  • 如果想使用空参构造,有两种方式:

    第一种可以使用Class类中newInstance()  
    第二种可以使用Constructor类中的newInstance()

    通常使用第一种方式。

方法对象

  • 获取方法对象

    • Method getMethod(String name, 类... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。

    • Method[] getMethods() 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。

    • Method getDeclaredMethod(String name, 类... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。

    • Method[] getDeclaredMethods() 返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。

  • 执行方法

    • Object invoke(Object obj,Class ... parametertype)

  • 获取方法的名称

    • String getName()

类加载过程

 

注解

注解概述

我们可以把注解理解为一种代码级别的说明,功能性说明,是从JDK1.5之后引入的新特性,格式:@注解名称

对比注释,是给开发者看的,带代码没有任何影响,注解,是给JVM看的,具有功能的代码。

  • 定义:也叫元数据,是一种具有代码级别的说明,它同接口、类、枚举是在同一层次上。它可以声明在类、方法、属性、包、局部变量、方法参数等上面,用来对这些元素进行说明,注释。

  • 本质:就是一个接口,该接口默认继承Annotation接口。

注解的作用

在目前的主流应用中主要是替代配置文件(如xml文件)

  • 在Servlet2.5之前不支持注解开发,从Servlet3.0开始支持注解开发,不再需要到web.xml文件中去注册Servlet信息

  • 优点:开发效率高,代码精简度高

  • 缺点:代码耦合性太强了,维护困难。

常见的内置注解(原生)

  • @Override:是在java.lang包中,告知编译期此方法是重写父类中的方法

  • @SuppressWarning:是在java.lang包中,告知编译期此处内部有风险,抑制编译时的警告信息。

    • 此注解需要搭配参数/属性才可以使用

    • 参数/属性的名称是value,参数类型是String[]

      • unused : 未使用

      • unchecked :未检查(强制类型转换时泛型参数使用未指定),使用List、ArraytList等未进行参数化产生的警告

      • deprecation:过时

      • all :抑制所有

  • @Deprecated:是在java.lang包中,告知编译期此方法是过时的,是不被鼓励的,可能有更好的方法替代了,但是被此注解标记的方法依然可以使用。

     

 

 

你可能感兴趣的:(单元测试 反射 注解)