单元测试Junit4

单元测试Junit4

1、单元测试入门

所谓单元测试,就是针对最小的功能单元,编写测试代码对其进行正确性测试。

我们想想,咱们之前是怎么进行测试的呢?

比如说我们写了一个学生管理系统,有添加学生、修改学生、删除学生、查询学生等这些功能。要对这些功能这几个功能进行测试,我们是在main方法中编写代码来测试的。

但是在main方法中写测试代码有如下的几个问题,如下图所示:

在这里插入图片描述

为了测试更加方便,有一些第三方的公司或者组织提供了很好用的测试框架,给开发者使用。这里介绍一种Junit测试框架。

Junit是第三方公司开源出来的,用于对代码进行单元测试的工具(IDEA已经集成了junit框架)。相比于在main方法中测试有如下几个优点。

在这里插入图片描述

在写之前还有几个注意事项:

2、反射实现执行注解的方法

1. 测试方法不能有返回值,只能是void    
2. 参数列表不能有参数
3. 只能是public修饰

在上一个笔记中的记录了注解和反射,当时也通过反射的技术获取到了注解中的所有的值,其实我们已经可以通过反射的技术获取到所有使用每个注解的方法,然后在调用其他方法。就比如被@Test注解修饰的方法,我们就可以通过下面的代码来获取到所有的方法,而且我们也会发现,这些方法只能是无参数,无返回值只能是public修饰,这样就更简单了。有如下的测试方法类,我们通过反射的手段来执行这个方法。

public class TestUtils {

    @Test
    public void testGetSum(){
        System.out.println("测试getSum");
    }
    @Test
    public void testMinus(){
        System.out.println("测试minus");
    }
    @Test
    public void testMultiply(){
        System.out.println("测试multiply");
    }
    @Test
    public void testBy(){
        System.out.println("测试by");
    }
}

通过反射执行所有的方法

public class MyReflect {
    public static void main(String[] args) throws Exception {
//        获取字节码对象
        Class<TestUtils> testUtilsClass = TestUtils.class;
//        获取所有的方法
        Method[] declaredMethods = testUtilsClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
//            判断是否有@Test注解
            Test annotation = declaredMethod.getAnnotation(Test.class);
            if (annotation!=null){
//                传入一个对象,没有参数,所以不用传
                declaredMethod.invoke(testUtilsClass.newInstance());
            }
        }
    }
}

结果如下:反射是不是很香。

测试getSum
测试minus
测试multiply
测试by

另外还有一些默认的规定找的网上的截图:主要就是测试的类名,比如Student类中的有一个方法study 对应的测试类和方法是

StudentTest testStudy

在这里插入图片描述

由于Junit是第三方提供的,所以我们需要把jar包导入到我们的项目中,才能使用,具体步骤如下图所示:

在这里插入图片描述

先准备一个类,假设写了一个StringUtil工具类,代码如下

public class StringUtil{
    public static void printNumber(String name){
        System.out.println("名字长度:"+name.length());
    }
}

接下来,写一个测试类,测试StringUtil工具类中的方法能否正常使用。

public class StringUtilTest{
    @Test
    public void testPrintNumber(){
        StringUtil.printNumber("admin");
        StringUtil.printNumber(null);
    }
}

写完代码之后,我们会发现测试方法左边,会有一个绿色的三角形按钮。点击这个按钮,就可以运行测试方法。

在这里插入图片描述

3、单元测试断言

接下来,我们学习一个单元测试的断言机制。所谓断言:意思是程序员可以预测程序的运行结果,检查程序的运行结果是否与预期一致。

我们在StringUtil类中新增一个测试方法

 public static int getMaxIndex(String data){
     if(data == null){
         return -1;
     }
     return data.length();
 }

接下来,我们在StringUtilTest类中写一个测试方法

public class StringUtilTest{
    @Test
    public void testGetMaxIndex(){
       int index1 = StringUtil.getMaxIndex(null);
       System.out.println(index1);
        
       int index2 = StringUtil.getMaxIndex("admin");
       System.out.println(index2);
        
        //断言机制:预测index2的结果
        Assert.assertEquals("方法内部有Bug",4,index2);
    }
}

运行测试方法,结果如下图所示,表示我们预期值与实际值不一致

在这里插入图片描述

4、Junit框架的常用注解

除了@Test注解,还有一些其他的注解,我们要知道其他注解标记的方法什么时候执行,以及其他注解在什么场景下可以使用。

注解说明
@Test测试方法
@Before用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。
@After用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeClass用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。
@AfterClass用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。

接下来,我们演示一下其他注解的使用。我们在StringUtilTest测试类中,再新增几个测试方法。代码如下

public class StringUtilTest{
    @Before
    public void test1(){
        System.out.println("--> test1 Before 执行了");
    }
    @BeforeClass
    public static void test11(){
        System.out.println("--> test11 BeforeClass 执行了");
    }
    @After
    public void test2(){
        System.out.println("--> test2 After 执行了");
    }
    @AfterClass
    public static void test22(){
        System.out.println("--> test22 AfterClass 执行了");
    }

    @Test
    public void testMethod(){
        System.out.println("hello");
    }
}

结果如下:

--> test11 BeforeClass 执行了
--> test1 Before 执行了
hello
--> test2 After 执行了
--> test22 AfterClass 执行了

我们现在已经知道每一个注解的作用了,那他们有什么用呢?应用场景在哪里?

我们来看一个例子,假设我想在每个测试方法中使用Socket对象,并且用完之后,需要把Socket关闭。代码就可以按照下面的结构来设计

public class StringUtilTest{
    private static Socket socket;
    @Before
    public void test1(){
        System.out.println("--> test1 Before 执行了");
    }
    @BeforeClass
    public static void test11(){
        System.out.println("--> test11 BeforeClass 执行了");
        //初始化Socket对象
        socket = new Socket();
    }
    @After
    public void test2(){
        System.out.println("--> test2 After 执行了");
    }
    @AfterClass
    public static void test22(){
        System.out.println("--> test22 AfterClass 执行了");
         //关闭Socket
        socket.close();
    }
    @Test
    public void testMethod(){
        System.out.println("hello");
    }
}

前面的注解是基于Junit4版本的,再Junit5版本中对注解作了更新,但是作用是一样的。下面就不做演示了

注解说明
@Test测试方法
@BeforeEach用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。
@AfterEach用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeAll用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。
@AfterAll用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yfs1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值