吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1578|回复: 6
收起左侧

[学习记录] Java基础之单元测试和注解学习笔记分享

  [复制链接]
mobaijun 发表于 2021-7-30 09:23

Junit单元测试

测试分类:

  • 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。
  • 白盒测试:需要写代码的。关注程序具体的执行流程。

黑盒测试和白盒测试

什么是单元测试

  • 对一部分代码进行测试

Junit介绍

Junit是一个Java语言的单元测试框架,属于白盒测试,简单理解为可以用于取代java的main方法。Junit属于第三方工具,需要导入jar包后使用。

什么是Junit:

  • 是第三方写的一个单元测试框架,可以取代main方法
  • Junit需要导入jar包,压缩包,里面有很多的java代码,因为Junit使用广泛,所以idea就已经包含了Junit,只需要引入即可

Junit的好处:

  • 可以单独测试一部分代码

Junit的使用步骤:

> 编写测试类
>
>
编写测试方法:
>
>    必须是public修饰符的
>
>   
必须是没有返回值的void
>
>    必须没有参数
>
>     > public void 方法名() {
>     >             测试代码
>     >          }
>
>   
给测试方法添加@Test注解
>
>    运行测试方法
>
>   
看结果
>
>      绿色:表示通过
>     
红色:表示失败

Junit的使用

  • 编写测试类,简单理解Junit可以用于取代java的main方法
  • 在测试类方法上添加注解 @test
  • @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
  • 添加Junit库到lib文件夹中,然后进行jar包关联
  • 使用:点击方法左侧绿色箭头,执行当前方法(方法必须标记@Test)。执行结果红色:代表失败;执行结果 绿色:代表成功
package com.mobai;

import org.junit.Test;
import java.util.Arrays;
/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * ClassName:Test
 * 类描述:Junit测试
 */
public class TestDemo1 {

    @Test
    public void test01() {
        for (int i = 0; i < 100; i++) {
            System.out.println(" i: " + Arrays.class.getClass());
        }
    }
}

常用注解

  • @Test,用于修饰需要执行的测试方法
  • @Before,修饰的方法会在测试方法之前被自动执行
  • @After,修饰的方法会在测试方法执行之后自动被执行
package com.mobai;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * ClassName:Test
 * 类描述:Junit测试
 */
public class TestDemo1 {

    @Before
    public void testBefore() {
        System.out.println(" 前置方法 ");
    }

    @After
    public void testAfter() {
        System.out.println(" 后置方法 ");
    }

    @Test
    public void test01() {
        for (int i = 0; i < 10; i++) {
            System.out.println(" i: " + Arrays.class.getClass());
        }
    }
}

Class对象

Class对象

  • 当程序需要用到Person类的时候会将Person.class加载到内存中
  • 将Person.class加载到内存,分别存放成员变量,成员方法,构造方法
  • Java虚拟机会主动创建一个Class对象,描述方法区中的Person.class的内容

反射的概念

> 什么是反射?

  • 在程序运行的过程中,通过Class对象得到类中构造方法,成员方法,成员变量,并操作他们

> 反射的应用场景

  • idea等开发工具的智能提示
  • 开发框架 SSM

> 反射的好处

  • 可以在程序运行过程中,操作这些对象。
  • 可以解耦,提高程序的可扩展性。

三种获取Class对象的信息

获取CLASS对象的方式 作用 应用场景
类名.class 通过类名的属性class获取 多用来传递参数
Class.forName(“类全名”) 通过指定的字符串路径获取 多用来加载配置文件,将类名定义在配置文件中,读取文件,加载类
对象.getClass() 通过对象的getClass()方法获取 多用来获取对象的字节码

三种获取Class对象的方式

  • 类名.class
  • 对象名.getClass()
  • Class.forName(类全名)/(类全名就是:包名.类名)

> 注意:这三种方式得到的都是同一个对象

/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * ClassName:TestClass
 * 类描述: 三种获取Class对象的方式
 */
public class TestClass {
    public static void main(String[] args) throws Exception {
        // 1.类名.class
        Class clz = Book.class;
        System.out.println("clz = " + clz);

        // 2.通过对象名.getClass()
        Book book = new Book();
        Class clz2 = book.getClass();
        System.out.println("clz2 = " + clz2);

        // 3.通过Class.forName(类全名)
        Class clz3 = Class.forName("com.mobai.annion.Book");
        System.out.println("clz3 = " + clz3);

        // 这三种方式得到的都是同一个对象
        System.out.println(clz2 == clz3);
        System.out.println(clz == clz2);
    }
}

获取Class对象的信息

常用方法:

String getSimpleName(); 获得简单类名,只是类名,没有包
String getName(); 获得完整类名,包含包名 + 类名
T newTnstatance(); 创建此Class对象所表示的类是一个新实例<br />要求:类必须有<public>的无参构造方法
public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1.得到Class对象
        Class clazz = Class.forName("com.mobai.annion.Book");

        // 2.调用方法getName
        String name1 = clazz.getName();
        // name1 = com.mobai.annion.Book
        System.out.println("name1 = " + name1);

        // 2.1调用方法getSimpleName
        String name2 = clazz.getSimpleName();
        // name2 = Book
        System.out.println("name2 = " + name2);
    }
}

反射获取public的构造方法

Constructor类作用:

  • 表示类中构造方法

如何得到public的Constructor对象:

  • 获取Class对象
  • 通过Class对象获取构造方法

> cls.getConstructor(); 获取一个public的构造方法
>
> cls.getConstructors(); 获取所有public的构造方法

  • Constructor类的方法:

    • newInstance(); 创建对象
  • 基本数据类型与引用数据类型的Class对象

    > int.class != Integer.class

  • 创建一个学生类
/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * ClassName:Student
 * 类描述: 学生类
 */
public class Student {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Student(String name) {
        this.name = name;
    }

    public Student(Integer age) {
        this.age = age;
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 测试类
public class TestDemo1 {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.mobai.fanshe.Student");
        // 1.获取所有public的构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("constructor = " + constructor);
        }

        // 2.获取一个public构造方法
        Constructor<?> constructors1 = clazz.getConstructor();
        // public com.mobai.fanshe.Student()
        System.out.println("constructors1 = " + constructors1);

        // 2.1反射获取指定的构造方法
        Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
        // public com.mobai.fanshe.Student(java.lang.String,java.lang.Integer)
        System.out.println("constructor = " + constructor);
    }
}

反射通过Constructor创建对象

public class TestDemo1 {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.mobai.fanshe.Student");
        // 1.获取所有public的构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("constructor = " + constructor);
        }

        // 2.获取一个public构造方法
        Constructor<?> constructors1 = clazz.getConstructor();
        // public com.mobai.fanshe.Student()
        System.out.println("constructors1 = " + constructors1);

        // 2.1反射获取指定的构造方法
        Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
        // public com.mobai.fanshe.Student(java.lang.String,java.lang.Integer)
        System.out.println("constructor = " + constructor);

        // 3.使用newInstance创建对象
        Object instance = constructor.newInstance("墨白君", 15);
        // Student{name='墨白君', age=15}
        System.out.println("instance = " + instance);
    }
}

反射获取声明的构造方法

声明的Constructor就是类中有的构造方法,不管权限

如何得到声明的Constructor:

  • 得到Class对象
  • 通过Class对象得到声明Constructor

> Declared的规律:
>
> cls.getConstructor();  获取一个public的构造方法
>
cls.getConstructors();  获取所有public的构造方法
> cls.getDeclaredConstructors(); 得到所有声明的构造方法
>
cls.getDeclaredConstructor(); 得到一个声明的构造方法
> 没有Declared是得到public的
>
有Declared是得到声明的
> 没有s的是得到一个
>
有s的是得到多个

对私有构造方法我们在使用之前调用

  • con.setAccessible(true); 暴力反射
  • 学生类
public class Student {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Student(String name) {
        this.name = name;
    }

    private Student(Integer age) {
        this.age = age;
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 测试类
public class TestDemo2 {
    public static void main(String[] args) throws Exception {
        // 1.获取Class对象
        Class<?> clazz = Class.forName("com.mobai.fanshe.Student");

        // 2.得到一个申明的构造方法
        Constructor<?> constructor = clazz.getDeclaredConstructor(Integer.class);
        // private com.mobai.fanshe.Student(java.lang.Integer)
        System.out.println("constructor = " + constructor);

        // 暴力反射
        constructor.setAccessible(true);
        // 创建对象
        Object instance = constructor.newInstance(16);
        System.out.println("instance = " + instance);
    }
}

Class的newInstance方法创建对象

Class的newInstance方法就是使用无参构造创建对象.

public class TestDemo3 {
    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> clazz = Class.forName("com.mobai.fanshe.Student");
        // 获取无参构造
        Constructor<?> constructor = clazz.getConstructor();
        // 通过无参构造创建对象
        Object instance = constructor.newInstance();
        // instance = Student{name='null', age=null}
        System.out.println("instance = " + instance);

        // Class对象创建对象的方法
        Student instance1 = (Student) clazz.newInstance();
        // instance1 = Student{name='null', age=null}
        System.out.println("instance1 = " + instance1);
    }
}

反射获取Method

  • Method类作用

    • 表示类中的方法
  • 如何得到Method对象

    • 得到Class对象
    • 通过Class对象获取Method
    • cls.getMethods(); 获取所有public的方法
    • cls.getMethod(); 获取一个public的方法
    • cls.getDeclaredMethods(); 获取所有声明的方法
    • cls.getDeclaredMethod(); 获取一个声明的方法
  • Method类中的方法: 得到Method就可以调用这个方法

    • Object invoke(Object target, Object... args);
    • Object target: 调用方法的对象
    • Object... args: 调用方法时传递的参数
    • Object: 返回值类型
  • 学生类
public class Student {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Student(String name) {
        this.name = name;
    }

    private Student(Integer age) {
        this.age = age;
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 通过class获取所有方法
public class TestDemo4 {
    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> clazz = Class.forName("com.mobai.fanshe.Student");
        // 通过CLass获取方法
        Method[] methods = clazz.getMethods();
        // 遍历获取所有public方法
        for (Method method : methods) {
            System.out.println("method = " + method);
        }

        // 获取一个方法
        Method setName = clazz.getMethod("setName", String.class);
        // setName = public void com.mobai.fanshe.Student.setName(java.lang.String)
        System.out.println("setName = " + setName);

        // 获取所有声明的方法
        Method[] methods1 = clazz.getDeclaredMethods();
        for (Method method : methods1) {
            System.out.println("method = " + method);
        }
        // 获取一个声明的方法
        Method getName = clazz.getDeclaredMethod("getName");
        // public java.lang.String com.mobai.fanshe.Student.getName()
        System.out.println("getName = " + getName);
    }
}

什么是注解?

> 注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、 接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

  • Annotnation的作用:

    • 说明程序的,给计算机解释
    • 可以被其他程序读取
  • Annotnation的格式

    • 注解是以"@注解名称"在代码中存在的,还可以添加一些参数
  • Annotnation在哪里使用?

    • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问
  • 作用分类:

    • 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
    • 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
    • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
  • 常见注解:

    • @author:用来标识作者名,eclipse开发工具默认的是系统用户名。
    • @since:  从那个版本开始
    • @version:用于标识对象的版本号,适用范围:文件、类、方法。
    • @Override:用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。

自定义注解

自定义注解: 注解本质上就是一个接口,该接口默认继承Annotation接口

public interface MyAnno extends java.lang.annotation.Annotation {}
  • 自定义注解
// 空注解
public @interface Anno01 {
}
  • 有参数的注解

只能使用Java提供的基本数据类型,String可以,Class可以,枚举类,其他暂未测试,包装类不可以.自定义类不可以

public @interface Anno02 {
    // 属性
    String name();
    double price() default 99;
    String[] authors();

//    Anno01 abc(); // 注解
//    WeekDay w();
//    Class p();
}

enum WeekDay {
    SUN, MON
}

class Person {

}

注解的属性类型

  • 八种基本数据类型
  • String,注解,枚举,Class
  • 以上类型的一维数组

> 自定义类不可以

使用自定义注解

  • 注解可以用来保存数据

  • 使用自定义注解格式:

    > @注解名(属性名=属性值, 属性名=属性值)

注意:注解的属性可以有默认值,当使用注解时不赋值就使用默认值,赋值就按照赋的值

  • 定义注解
package com.mobai.annaction;

// 自定义注解
public @interface MoBai {
    // 名字
    String name();

    // 默认属性
    String value() default "框架师";
}
  • 使用注解
public class AnnactionTest {

    @MoBai(name = "墨白",value = "")
    public static void main(String[] args) {
    }

    @Test
    public void annTest(){
    }
}

自定义注解的特殊情况

当注解只有一个属性,并且属性名是value时,在使用注解时可以省略属性名

  • 自定义注解
public @interface MoBai {
    String value();
}
  • 使用注解
@MoBai("abc")
public class Demo11 {
    @MoBai(value = "abc")
    public static void main(String[] args) {
    }
}

元注解

  • @Target
  • @Retention

> 修饰注解的注解叫做元注解

@Target元注解:
  • 默认情况注解可以放在任意位置

    > 限制注解可以放在哪些位置
    >   
    @Target(ElementType.TYPE)           注解只能放在类或者接口上
    >    @Target(ElementType.CONSTRUCTOR)    注解只能放在构造方法上
    >   
    @Target(ElementType.FIELD)          注解只能放在成员变量上
    >    @Target(ElementType.METHOD)         注解只能放在成员方法上
    >   
    @Target(ElementType.LOCAL_VARIABLE) 注解只能放在局部变量上

@Retention元注解:
  • 默认是CLASS阶段

> 限制注解可以活到什么时候
>
>   >
SOURCE = = = = = = = = = = >>CLASS = = = = = = = = = = = = = >>RUNTIME
>   > * 源代码阶段(.java) = = = = >>编译 = = = >>.class = = = = = = >>运行

  • 自定义注解
//@Target(ElementType.TYPE) // 注解只能放在类或者接口上
//@Target(ElementType.CONSTRUCTOR) // 注解只能放在构造方法上
//@Target(ElementType.FIELD) // 注解只能放在成员变量上
//@Target(ElementType.METHOD) // 注解只能放在成员方法上
//@Target(ElementType.LOCAL_VARIABLE) // 注解只能放在局部变量上
@Retention(RetentionPolicy.RUNTIME)
public @interface MoBai {
}
  • 使用注解
@MoBai
public class Demo12 {
    @MoBai
    private String a;

    @MoBai
    public Demo12() {

    }

    @MoBai
    public static void main(String[] args) {
        @MoBai
        int x = 10;
    }
}

注解的解析

  • 什么是注解解析?

> 获取注解中保存的数据

  • 注解解析相关接口?

> AnnotatedElement接口中:
>
>   
Annotation getAnnotation(Class<T> annotationClass) 获取一个注解
>
>    Annotation[] getAnnotations()  获取多个注解
>
>   
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断有没有指定的注解
>
>     > 注意: Constructor , Field , Method实现了AnnotatedElement接口

  • 如何解析注解?

> 注解在谁头上,就用谁来获取注解
>
注解在构造方法上,使用Constructor对象获取注解
> 注解在成员方法上,使用Method对象获取注解
>
注解在成员变量上,使用Field对象获取注解
> * 使用反射

  • 创建自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * [@]Interface:MoBook
 * 注解描述: 自定义注解
 */
// 限定方法使用
@Target(ElementType.METHOD)
// 活到运行时候
@Retention(RetentionPolicy.RUNTIME)
public @interface MoBook {
    String name();

    double price();

    String[] authors();
}
  • 定义数据类使用注解
/**
 * Software:IntelliJ IDEA 2020.1 x64
 * Author: MoBai·杰
 * ClassName:Book
 * 类描述: 书籍类
 */
public class Book {
    @MoBook(name = "框架师", price = 25.0, authors = "墨白")
    public void sell() {

    }
}
  • 测试类
public class TestMoBook {
    public static void main(String[] args) throws Exception {
        // 1.获取Class对象
        Class<?> className = Class.forName("com.mobai.annion.Book");
        // 2.获取Method对象
        Method method = className.getMethod("sell");
        // 3.通过method对象获取注解
        Annotation[] annotations = method.getAnnotations();
        // 4.遍历数组
        for (Annotation annotation : annotations) {
            System.out.println("annotation = " + annotation);
        }
        // 3.3 boolean isAnnotationPresent​(Class<? extends Annotation> annotationClass)
        //  判断有没有指定的注解
        boolean b = method.isAnnotationPresent(MoBook.class);
        System.out.println(b);
        if (b) {
            // 3.2 Annotation getAnnotation​(Class<T> annotationClass) 获取一个注解
            MoBook ann = method.getAnnotation(MoBook.class);
            System.out.println(ann.name() + "::" + ann.price() + "::" + Arrays.toString(ann.authors()));
        }
    }
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lyj996 发表于 2021-7-30 10:19
好,学习了
13502501892 发表于 2021-7-30 10:28
jasonwood 发表于 2021-7-30 13:01
不知道改成啥 发表于 2021-7-30 13:38
mk下,正在转java...
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-1 06:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表