写好一个class之后,再写另外一个class用来测试自己写好的类里面的方法。
例如我自己定义的类里有一个User类:
public class User{
private int id;
private String name;
private double salary;
private String time;
public User() {
}
public User(int id, String name, double salary, String time) {
super();
this.id = id;
this.name = name;
this.salary = salary;
this.time = time;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "["+this.id+","+this.name+","+this.salary+","+this.time+"]";
}
public void run() {
System.out.println("["+this.id+","+this.name+","+this.salary+","+this.time+"]");
}
public void eat() {
System.out.println("eating");
}
}
这时候我要进行单元测试的话,就写另外一个类来利用Junit进行测试:
一、Junit的test注解的方法:
public class testUser {
@Test
public void testRun() {
//写这个方法测试User的run方法,前面@test会自动调用
User user=new User();
user.setId(1222);
user.setName("name");
user.setSalary(215434);
user.setTime("2018");
user.run();
}
}
我们知道以往的的java文件是必须要有main方法才会进行执行,它是程序执行的入口,但是利用Junit进行单元测试的时候,有了一个**@Test**这样的注解,就可以交给JUnit来进行测试了,我们右键这个文件,run as 会有 run as Junit的选项,然后会出现这样的视图:
可以看到,全部是绿色的进度条,说明测试的这个run方法成功的运行了,没有异常也没有错误。
我们的user类里也还有另一个方法eat,要测试的话,我们就在这个测试java文件里再写进另一个方法:
@Test
public void testEat() {
//写这个方法测试User的run方法,前面@test会自动调用
User user=new User();
user.setId(1222);
user.setName("name");
user.setSalary(215434);
user.setTime("2018");
user.eat();
}
然后就run as junit就可以看到这个单元测试的结果。
建议是测试类的时候都使用JUnit,因为当使用单独的main方法来测试的时候是有一个先后顺序的问题,如果想要单独的是方法,就要把其他的注释掉,然后通过断点,跳过等等操作,来定位问题的位置,而JUnit可以帮助我们定义到每一个具体的方法执行直接右键run as 就可以。
二、Before和After注解的方法(Junit5和4有不同)
另外,在使用JUnit进行测试的时候,我们一般还会在测试类的最开始和最后加上before和after方法:
@Before
public void Before() {
System.out.println("before");
}
@After
public void after() {
System.out.println("after");
}
这两个方法只要我们前面加了@Before和@After的注解(Junit4),他自己就会去执行,他存在的意义是什么呢?
当我们需要测试的内容非常多的时候,这两个注解的位置之前和之后,在Before的时候需要分配所需的资源等等,到After的位置应该释放对应的资源。那么对应的代码就可以写在这两个方法的内容里,其他我们想要干什么当然也可以进行更改。
比如我们刚刚测试User类的两个方法,写的两个测试方法里都new了对象,如果需要测试的方法非常多,那么中间过程会一直消耗内存,因此可以在我们Before的位置写的before方法里,new一个对象出来,那么接下来的测试方法里直接调用他去运行方法就可以了。
public class testUser2 {
private User user1=new User(1222,"name",215434,"2018");
@Before
public void before() {
}
@Test
public void testRun() {
user1.run();
}
@Test
public void testEat() {
user1.eat();
}
@After
public void after() {
System.out.println("after");
}
}
运行结果:
其实,before方法里可以对对象进行定义,最前面只用声明这个user1就可以了,但是我发现按照这种方法运行会报空指针错误,但是并不应该这样,于是百度了一下,发现是Junit版本的问题,我的Junit是5,而从Junit4到Junit5的语法有改变:
所以在Junit5的情况下,在before和after里控制一些在测试之前和之后的资源相关问题,可以用BeforeEach和AfterEach注解来完成:
public class testUser3 {
private User user2;
@BeforeEach
public void before() {
user2=new User(1222,"name",215434,"2018");
}
@Test
public void testRun() {
user2.run();
}
@Test
public void testEat() {
user2.eat();
}
@AfterEach
public void after() {
System.out.println("after");
}
}
这个情况就不会报空指针错误了。
运行结果:
看到了吗,有两个after输出,可以看出Junit5这里对整个注解关键词的改变还是更见名知意了,毕竟是BeforeEach,就是对每一个test方法之前和之后都进行了这个操作。
那么针对Junit5而言,在写测试类的时候一般还要写另外两个特殊的方法:BeforeAll和AfterAll(上面的图里记录过了,在Junit4里面是BeforeClass和AfterClass)
这两个方法的特点是在类加载的时候运行,也就是在所有测试方法之前和之后,只运行一次,写的时候要**用static修饰**。
public class testUser4 {
@BeforeAll
public static void beforeAll() {
System.out.println("beforeAll");
}
private User user2=new User(1222,"name",215434,"2018");
@Test
public void testRun() {
user2.run();
}
@Test
public void testEat() {
user2.eat();
}
@AfterAll
public static void afterAll() {
System.out.println("afterAll");
}
}
这样的运行结果是:
可以看到在类加载的时候,所有的测试方法最前面以及运行完毕,类的最后面,有执行这两个方法。
三、Junit中的断言Assertions(对应Junit4中的Assert,已被废弃)
Junit中提供的Assert类,意思是断言,判断各种返回值和设计时候的期待值的对比,从而一个一个来测试到底哪个地方出了问题,这个类里提供了很多方法。
例如首先我们在前面的User类里增加一个有返回值的方法:
public String addId() {
return "ID:"+id;
}
这样的话,我们期待程序调用到这方法的时候能够返回的是一个字符串,是“ID:xx”的形式。
@Test
public void testaddID() {
Assert.assertEquals("ID:1222", user2.addId());
}
这个方法前面的参数是expected值,后面是actual值。
现在在Junit5中,对应的类应该是Assertions:
@Test
public void testaddId() {
Assertions.assertEquals("ID:1222", user2.addId());
}
运行结果就是全绿条通过,如果我们expected的位置填入的错误,或者方法错误,那么实际上方法的返回值会判断结果出错,就会出现红条,比如我把上面的assertEquals方法里面的expected值改成122(写的方法没有错,测试的expected错了,为了查看测试结果):
可以看到,下面的具体描述,期望值和实际运行方法的返回值不同。
在Assertions里还有很多方法供我们直接调用,我们看看outline:
到这里Junit工具的大概使用我们已经够用了。