Java的单元测试、反射、注解、枚举

前言

本文主要介绍Java中Junit、注解、枚举的概念。

一、Junit单元测试

软件测试的目的:软件开发的目的是交付给用户一个正确、稳定的项目,为了保证项目的稳定性,我们就需要对代码进行测试之后再上线进而交付给用户;

测试的分类:测试分为黑盒测试和白盒测试,其中黑盒测试仅仅在软件功能层面对我们的代码进行测试(不关注代码逻辑),而白盒测试需要写代码,对项目代码进行测试。

1.引入Junit

如果需要对业务代码进行测试一定要在main方法(程序的入口)进行;

测试的逻辑如果要分开的话,需要定义多个测试类或者测试方法,比较麻烦;

业务代码

package com.zhanggen.calcaulator;

public class Calculator {
    //加法
    public int add(int a, int b) {
        return a + b;
    }

    //减法
    public int sub(int a, int b) {
        return a - b;
    }


}
Calculator.java

--------------------------

测试代码

package com.zhanggen.calcaulator;

import java.util.Calendar;

public class test {

    public static void main(String[] args) {
        //测试计算器的功能
        Calculator cal = new Calculator();

        //测试加法逻辑
        int result = cal.add(10, 10);
        System.out.println(result);

        //测试减法逻辑
        int resuit2 = cal.sub(20, 10);
        System.out.println(resuit2);

    }
}
test.java

2.使用junit

使用junit,我们可以在不使用main方法的情况下独立运行Java类中定义的所有方法

 ---------------

package com.zhanggen.test;

import com.zhanggen.calcaulator.Calculator;
import org.junit.Assert;
import org.junit.Test;

public class CalculatorTest {
    //测试add方法
    @Test
    public void testAdd() {
        //测试add方法
        Calculator cal = new Calculator();
        int result = cal.add(10, 20);
        //加入断言:判断一下我预测的结果和实际的计算出来的结果是否一致?
        Assert.assertEquals(30, result);
    }

    //测试sub减法
    @Test
    public void testSub() {
        //测试sub方法
        Calculator cal = new Calculator();
        int result = cal.sub(30, 20);
        //加入断言:判断一下我预测的结果和实际的结果是否一致?
        Assert.assertEquals(10, result);


    }
}
代码

3.@Before和@After注解

在某一个方法中,加入@Before注解之后,那么该方法中的功能,会在测试方法执行前执行;通常用于申请资源;

在某一个方法中,加入@After注解之后,那么该方法中的功能,会在测试方法执行后执行;通常用于释放申请的资源;

package com.zhanggen.test;

import com.zhanggen.calcaulator.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {

    @Before
    public void start() {
        System.out.println("申请资源");
    }

    @After
    public void end() {
        System.out.println("释放资源");
    }

    //测试add方法
    @Test
    public void testAdd() {
        //测试add方法
        Calculator cal = new Calculator();
        int result = cal.add(10, 20);
        //加入断言:判断一下我预测的结果和实际的计算出来的结果是否一致?
        Assert.assertEquals(30, result);
        System.out.println("执行add方法的测试!");
    }

    //测试sub减法
    @Test
    public void testSub() {
        //测试sub方法
        Calculator cal = new Calculator();
        int result = cal.sub(30, 20);
        //加入断言:判断一下我预测的结果和实际的结果是否一致?
        Assert.assertEquals(10, result);
        System.out.println("执行sub方法的测试!");


    }
}

二、反射

反射是Java提供的一套动态执行API,Java框架底层都是使用反射实现的

动态功能的软件都是利用反射实现的,软件在执行前,不知道类型,不知道方法名,需要使用反射实现;

 1.反射是什么?

反射是Java提供的一套动态执行API。

2.反射的功能

动态根据类名加载类到内容

动态根据类型创建对象

动态访问属性和方法

动态打开访问权限,访问被private修饰的属性和方法 

3.获取类API

我们使用c小写的class定义类,使用C大写的Class代表反射获取的对象;

方式1:Class.forName("类名"),根据类名动态获取Class对象,适合根据动态给定的类名,创建Class对象;

package com.company;

import java.util.Scanner;

public class Demo01 {

    public static void main(String[] args) throws Exception {
        //利用Class.forName()动态获取类
        System.out.printf("请输入类名:");
        Scanner sc = new Scanner(System.in);
        String className = sc.next().trim();
        Class cls = Class.forName(className);
        System.out.println(cls);

    }
}
View Code

方式2:类型.class属性获取Class对象,适合直接根据类名获得Class对象;

package com.company;

import java.io.File;

public class Demo02 {
    public static void main(String[] args) {
        /*
        Java所有类型都有1个默认属性 .class;
        是静态获得类型,不能体现动态性;
        */
        Class cls = String.class;
        cls = int.class;
        cls = File.class;
        cls = Foo.class;
        System.out.println(cls);

    }
}
View Code

方式3:对象.getClass()获得对象的类型,适合已经存在的对象;

package com.company;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class Demo03 {
    public static void main(String[] args) {
        /*
        在Java中所有对象都包含1个.getClass()方法;
        利用对象的getClass方法,获取对象的类型,该方法经常于动态检查某个对象的类型;
        * */
        Class cls = "ok".getClass();                         //class java.lang.String
        cls = new Integer(2390).getClass();    //class java.lang.Integer
        cls = System.in.getClass();                   //class java.io.BufferedInputStream
        cls = System.out.getClass();                  //class java.io.PrintStream
        System.out.println(cls.getClass());

        List<String> list = new ArrayList<>();
        Iterator<String> i = list.iterator();
        System.out.println(i.getClass()); //class java.util.ArrayList$Itr  $代表Itr是ArrayList的内部类

        list = new LinkedList<>();
        Iterator<String> i1 = list.iterator();
        System.out.println(i1.getClass());


    }
}
View Code

4.根据类名创建对象API

package com.company;

import java.util.Scanner;

public class Demo04 {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入类名:");
        //动态加载Class对象
        String className = sc.nextLine().trim();
        Class cls = Class.forName(className);
        //之前是静态的,现在动态创建对象;
        Object obj = cls.newInstance();
        System.out.println(obj);


    }
}

5.访问对象的属性

package com.company;

import java.lang.reflect.Field;

public class Demo05 {
    public static void main(String[] args) throws Exception {
        String className = "com.company.Foo";
        Class cls = Class.forName(className);
        //获取所有属性列表
        Field[] fieldList = cls.getDeclaredFields();
        //跟属性名称获取单个属性
        Field name = cls.getDeclaredField("name");
        System.out.println(name);

        //获取所有属性
        for (Field field : fieldList) {
            System.out.println(field);
        }


    }
}

6.获取字段的值

通过反射可以获取 对象的属性值也可以修改对象的属性值;

package com.company;

import java.lang.reflect.Field;

public class Demo06 {
    //动态获取对象字段的值
    public static void main(String[] args) throws Exception {
        //根据字符串获取类
        Class cls = Class.forName("com.company.Foo");
        //类实例化出1个对象
        Object obj = cls.newInstance();
        //获取name字段并获取该字段的值
        Field nameField = cls.getDeclaredField("name");
        Object nameValue = nameField.get(obj);
        System.out.println((String) nameValue);

        //获取age字段并获取该字段的值
        Field ageField = cls.getDeclaredField("age");
        Object ageValue = ageField.get(obj);
        System.out.println((int) ageValue);

        //获取私有字段的值
        Field salaryField = cls.getDeclaredField("salary");
        //由于salary字段是私有属性,所以反射在获取其属性值时必须夺权;
        salaryField.setAccessible(true);
        Object salaryValue = salaryField.get(obj);
        System.out.println((long) salaryValue);

        //------------修改对象的属性----------------------//
        salaryField.set(obj,99999999);
        salaryValue = salaryField.get(obj);
        System.out.println((long) salaryValue);



    }
}

7.动态执行方法

使用反射API可以动态获取并执行对象的方法;

package com.company;

import java.lang.reflect.Method;

public class Demo07 {
    public static void main(String[] args) throws Exception {
        String className = "com.company.Foo";
        Class cls = Class.forName(className);
        //查询所有的方法
        Method[] methodArray = cls.getDeclaredMethods();
        for (Method method : methodArray) {
            System.out.println(method);
        }
        //根据方法名称获取方法:方法名称和方法参数类型
        Method method = cls.getDeclaredMethod("walk", String.class);
        System.out.println(method);
        //执行方法
        Object obj = cls.newInstance();
        method.invoke(obj, "光明路");

        //获取私有方法
        Method hugeMethod = cls.getDeclaredMethod("huge", String.class);
        hugeMethod.setAccessible(true);
        System.out.println(method);
        //执行私有方法
        hugeMethod.invoke(obj, "光明");

    }
}

  

三、注解(annotation)

注解是Java 5开始提供的新语法,用于为程序添加附件功能;

注解和反射的联系非常密切,在软件运行期间利用反射API,查找到注解,根据注解信息添加附件功能;

Java很多框架底层都是利用 注解+反射机制,实现框架的功能附加功能的;

1.注解使用流程

(1).定义注解

(2).在类/字段/属性/方法上标注注解

(3).在软件运行期间利用反射API,查找注解,根据注解信息添加附件功能

2.注解传播范围

参考

原文地址:https://www.cnblogs.com/sss4/p/15614329.html