• 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.注解传播范围

    参考

  • 相关阅读:
    系统吞吐量(TPS)、用户并发量、性能测试概念和公式
    javascript 匿名函数和闭包
    构建高可扩Web架构和分布式系统实战
    Javascript prototype 的作用
    myeclipse下载地址
    tomacat7.0配置(windows)
    IEEE802.11
    C#(多态)
    C#(泛型集合的使用)
    C#(对象引用)
  • 原文地址:https://www.cnblogs.com/sss4/p/15614329.html
Copyright © 2020-2023  润新知