junit&注解&枚举
junit单元测试
引入
1.软件测试的目的:
软件测试的目的是在规定的条件下对程序进行操作,已发现程序错误,衡量软件的质量,并对其是否能满足实际要求进行评估的过程。
2.测试分类
(1)黑盒测试:
软件的黑盒测试意味着测试要在软件的接口处进行,这种方法是吧测试对象看作一个黑盒子,测试人员完全不考虑程序内部逻辑结构和内部特征,只依据程序的需求规格说明书检查程序的功能是否符合它的功能说明。因此黑盒测试又叫做功能测试。
(2)白盒测试:junit属于白盒测试
软件的白盒测试是对软件的过程性细节做细致检查,这种方法是吧测试对象看作一个打开的盒子,它允许测试人员利用程序的内部的逻辑结构及有关信息设计过选择测试用例,对程序的所有逻辑路径进行测试,通过在不同点检查程序状态,确定实际状态是否与预期状态一致。因此白盒测试又叫做结构测试。
没用junit测试时候的缺点:
1.测试一定要走main方法,是程序的入口,main方法的格式必须正确不能写错。
2.要是再同一个main方法中测试,那么不需要测试的需要注释掉。
3.测试逻辑如果分开,需要定义多个测试类,太麻烦。
4.业务逻辑和测试代码会混淆。
junit
1.一般测试和业务做一个分离,分离为不同的包
2.测试方法的定义==》这个方法可以独立运行不依赖main方法
建议:见名知意 无参 无返回值
3.测试方法定义完以后,不能直接测试就独立运行,必须在方法前加入一个注解:@Test
4.导入junit依赖的环境(包):


5.测试代码块:
package com.junit;
import org.junit.Test;
public class ClaculatorTest {
//测试add
6.测试结果:
绿色:测试正常 红色:出现异常
7.注意:即使测试出现绿色效果,也不意味着测试完全通过,因为代码中逻辑也可能出现问题,这种情况下解决办法----加入断言,使用---Assert.assertEquals()方法
//测试sub
@Before,@After
@Before:某一个方法中,加入了@Before注解后,那么这个方法中的功能会在测试方法执行前先执行
一般会在@Before修饰的那个方法中加入一些申请资源的代码(申请数据资源、申请IO资源、申请网络资源。。。)
@After:某一个方法中,加入了一个@After注解后,那么这个方法中的功能会在测试后执行
一般会在@Before修饰的那个方法中加入一些释放资源的代码(释放数据资源、释放IO资源、释放网络资源。。。)
代码:
注解
引入
1.历史
JDK5.0新增 --- 注解(Annotation),也叫元数据
2.什么是注解?
注解就是代码里的 特殊标记,这些标记可以在编译、类加载、运行时被读取,并且执行相应的处理。通过注解程序员可以在不改变原有逻辑的情况下在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或进行部署。
*使用注解时要在其前面增加@符号,并把该注解当成一个 修饰符 使用,用于修饰它支持的程序元素。
3.注解的重要性
Annotation可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被保存在Annotatoin的"name=value"对中。在JavaSE中注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在javaEE/Arldroid中注解占据了更重要的角色,例如用来配置应用程序的任何切面, 代替JavaEE旧版中所遗留的繁冗与代码和XML配置等。 未来的开发模式都是基于注解的,JPA(java的持久化APL)是基于注解的,Spring2.5以.E都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的,注解是一种趋势,一定程度上可以说: 框架=注解+反射+设计模式
注解的使用实例
junit的注解
文档相关的注解
说明注释允许你在程序中嵌入相关与程序的信息,你可以使用javadoc工具软件来生成信息,并输出到HTML中。
说明注释使你更加方便的记录你的程序信息。
文档注解我们一般使用在文档注释中,配合javadoc工具。
javadoc 工具软件识别的标签:

注意
@param @return @exception这三个标记都是只用于方法的
@param的格式要求:@param 形参名 形参类型 形参说明
@return的格式要求:@return 返回值类型返回值说明,如果方法的返回值类型是void就不能写
@exception的格式要求:@exception 异常类型 异常说明
@param @exception 可以并列多个
代码:
package com.liu;
public class Person {
/**
* @param num1 吃饭人数
* @param num2 点餐数量
*/
public void eat(int num1,int num2){}
/**
* @param age 年龄
* @return int
* @exception ArithmeticException 算数异常
* @exception ArrayIndexOutOfBoundsException 下标越界异常
* @see Student
*/
public int ssleep(int age){
new Student();
if (age>100){throw new ArithmeticException();}
if (age<0){throw new ArrayIndexOutOfBoundsException();}
return 18;
}
}
IDEA中的javadoc使用

防止乱码:-encoding utf-8 -charset utf-8

JDK内置的 3 个注解
@Override:限定重写父类方法,该注解中能用于方法
public class Person {
public void eat(int num1,int num2){System.out.println("aaa");}
}
public class Student extends Person{
@Deprecated:用于表示所修饰的元素(类、方法、构造器、属性等)已过时。通常时因为所修饰的结构危险或存在更好的选择。

@SuppressWarnings:抑制编译器警告
![]()
使用@SuppressWarnings("unused")抑制未使用警告
![]()

使用@SuppressWarnings("rawtypes")抑制是原始类型警告


实现代替配置文件功能的注解
自定义注解
自定义注解一般很少使用,一般都用现成的注解
1.如何自定义注解


发现自定义的注解的声明使用的关键字:@interface,跟接口没有一点关系
2.内部的注解
以@SuppressWarnings为例:发现内部为:String[] value();
这value是属性还是方法?
--看上去是无参数方法,实际上理解为一个成员变量/一个属性
无参数方法名字 ==》成员变量的名字
无参数方法的返回值 ==》成员变量的类型
这个参数叫做配置参数
无参数方法的类型:基本数据类型(八种)、String、枚举、注解类型、还可以是以上类型对应的数组
3.使用自定义注解
使用注解时,如果定义了配置参数,就必须给配置参数进行赋值
@MyAnnotation(value = {"aaa","bbb","ccc"})
public void add(){
}
如果只有一个参数,并且这个参数的名字时value,’value=‘ 可以省略不写。
@MyAnnotation({"aaa","bbb","ccc"})
public void add(){
}
如果在自定义注解时给配置参数设置值了,那么在使用这个自定义的注解时就不需要传值了
public @interface MyAnnotation2 {
String value() default "abc";
}
public class Person {
@MyAnnotation2
@MyAnnotation({"aaa","bbb","ccc"})
public void add(){
}
}
一个注解的内部是可以不定义配置参数的:
public @interface MyAnnotation3 {
}
内部没有定义配置参数的注解 ==》可以叫做标记
内部定义配置参数的注解 ==》可以叫做元数据
元注解
元注解时用于修饰其它注解的注解
JDK5.0提供了四种元注解:Retention,Target,Documented,Inherited
@Retention
@Retention用于修饰注解,用于指定修饰的那个注解的生命周期,@Retention包含一个RetentionPolicy枚举类型的成员变量,使用@Retention时必须为该value成员变量指定值。
1.RetentionPolicy.SOURCE
在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注解,在.class文件中不会保留注解信息
2.RetentionPolicy.CLASS
在.class文件中有效(即class保留),保留在class文件中,但是当运行java程序时它就不会继续加载了,不会保留在内存中,JVM不会保留注解,如果注解没有加Retention元注解,那么相当于默认的注解就是这种状态。
3.RetentionPolicy.RUNTIME
在运行时有效(即运行时保留),当运行java程序时,JVM会保留注解加载在内存中,那么程序可以通过反射获取该注解
@Target
用于修饰注解的注解,用于指定被修饰的注解能用于修饰那些程序元素。@Target也包含一个名为value的成员变量。
1.图解

@Target({TYPE,FIELD,CONSTRUCTOR,METHOD})
public @interface MyAnnotation4 {
}


2.@Target() value值:
TYPE :类 FIELD :属性 CONSTRUCTOR :构造器 METHOD :方法 PARAMETER :参数
PACKAGE :包 LOCAL_VARIABLE ANNOTATION_TYPE TYPE_PARAMETER TYPE_USE
@Documented(很少用)
用于指定被该元注解修饰的注解将被javadoc工具提取成文档。默认情况下javadoc时不包括注解的,但是加上了这个注解,生成的文档中就会带着注解了
@Inherited(极少用)
被它修饰的Annotation将具有继承性,如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。
枚举
java中,类的对象个数是有限的,确定的,那么这个类就可以定义为枚举类
如:星期 ===》 星期一二三四五六日;
季节 ===》春夏秋冬
自定义枚举类
public class Season {
//属性
private final String seasonName;//季节名
private final String seasonDesc;//季节描述
private Season(String seasonName,String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
public static final Season SPRING=new Season("春天","春暖花开");
public static final Season SUMMER=new Season("夏天","烈日炎炎");
public static final Season AUTUMN=new Season("秋天","硕果累累");
public static final Season WINTER=new Season("冻天","寒风凛冽");
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
测试类
public static void main(String[] args) {
Season s1=Season.SPRING;
Season s2=Season.SUMMER;
Season s3=Season.AUTUMN;
Season s4=Season.WINTER;
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}
enum关键字
JDK1.5之后使用enum关键字创建枚举对象

//自定义枚举类--季节
public enum Season2 {
//提供枚举的有限的确定的对象===》enum枚举类要求对象(常量)必须放在开始的位置。
// 对象与对象之间用“,”隔开 最后用“;”结束
SPRING("春天","春暖花开"),
SUMMER1("夏天","烈日炎炎"),
AUTUMN("秋天","硕果累累"),
WINTER("冻天","寒风凛冽");
//属性
private final String seasonName;//季节名
private final String seasonDesc;//季节描述
private Season2(String seasonName, String seasonDesc){
this.seasonName=seasonName;
this.seasonDesc=seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
测试类
public static void main(String[] args) {
Season2 s1=Season2.SPRING;
System.out.println(s1);
//enum关键字对应枚举类的上层父类是 : java.lang.Enum
//但是我们自己定义的枚举类的上层父类是 : Object
System.out.println(Season2.class.getSuperclass().getName());//java.lang.Enum
}
最简单的枚举形态
public enum Season3 {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
因为这个枚举类底层没有属性,(属性,构造器,toString,get方法都删除了),按理来说应该写为SPRING(),现在可省略成不带括号的。
Enum类常用的方法
.toString() .values() .valueOf()
public class Test3 {
public static void main(String[] args) {
//toString();===》获取对象的名字
Season3 spring = Season3.SPRING;
System.out.println(spring.toString());
System.out.println("=============");
//values:返回枚举对象的数组
Season3[] s=Season3.values();
for (Season3 s3:s
) {
System.out.println(s3);
}
System.out.println("=============");
//valueOf ====》通过对象名字,获取这个对象
//注意:对象名字必须传输正确,否则报出异常
Season3 autumen1=Season3.valueOf("SPRING");
System.out.println(autumen1);
}
}
枚举类实现接口
1.先定义一个接口
public interface TestInterface {
void show();
}
2.枚举类实现接口,并且重写方法
public enum Season4 implements TestInterface{
SPRING,
SUMMER,
AUTUMN,
WINTER;
@Override
public void show() {
System.out.println("这是Enum实现的接口重写方法");
}
}
3.测试
public static void main(String[] args) {
Season4 spring = Season4.SPRING;
spring.show();//这是Enum实现的接口重写方法
Season4 winter = Season4.WINTER;
winter.show();//这是Enum实现的接口重写方法
}
发现所有的枚举对象调用的方法都是同一个方法,返回的结果都一样
下面更改为不同的枚举调用相同的方法,返回不一样的结果
public enum Season4 implements TestInterface{
SPRING{
@Override
public void show() {
System.out.println("这是春天");
}
},
SUMMER{
@Override
public void show() {
System.out.println("这是夏天");
}
},
AUTUMN{
@Override
public void show() {
System.out.println("这是秋天");
}
},
WINTER{
@Override
public void show() {
System.out.println("这是冬天");
}
};
}
枚举的实例应用
1.实例卡性别
1.创建性别的枚举类
public enum Sex {
男,女;
}
2.创建学生类
public class Student {
private String name;
private int age;
private Sex sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
public Student(String name, int age, Sex sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
3.测试类
public static void main(String[] args) {
Student s=new Student();
s.setName("lili");
s.setAge(19);
s.setSex(Sex.女);
System.out.println(s.toString());//Student{name='lili', age=19, sex=女}
}
2.结合枚举通过switch处理:
1.用上面的性别枚举类
2.swtich测试类
public static void main(String[] args) {
Sex sex=Sex.女;
switch (sex){
case 女:
System.out.println("这是女孩");
break;
case 男:
System.out.println("这是男孩");
break;
default:
break;
}
}
浙公网安备 33010602011771号