如何使用Java的JUnit进行单元测试,JUnit简单学习和实践

本文深入讲解JUnit单元测试的使用方法,包括@Test注解的基本应用,Before和After注解的资源管理,以及断言Assertions的详细解释,帮助读者掌握有效的单元测试技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写好一个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工具的大概使用我们已经够用了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值