单元测试

单元测试的好处:编写“高内聚低耦合”的代码有了一条统一的实现路径

单元的定义:单元如何定义取决于你如何定义“一件事”。只要这个“单元”里做的是“同一件事”,哪怕是其中定义了3个方法,它也可以是一个“单元”。

                    比如:写一个下订单的单元测试,可以把生成订单的方法和扣减红包的方法放在一起做单元测试,这样比两个方法分别做单测还可以多做一些关联验证,例如,订单上的红包金额是否与扣减的红包金额一致?

如何判断单元测试的好坏

第一级:大部分代码不需要Mock就可以测试。最优秀

第二级:大部分代码需要Mock才能测试,但都不是静态方法。

第三级:大部分代码需要Mock才能测试,而且包含大量静态方法。(一般的Mock工具还无法Mock静态方法)

确定单元测试的范围

1:公共组件库。这些代码变更不会特别频繁,覆盖率需要尽量达到100%。

2:被调用频次越高的代码。比如:登录验证,权限获取,项目列表获取等。

单元测试的标准

L1:输入正确的参数时,会有正确的输出(测试正确的处理逻辑是否符合预期)

L2:输入错误的参数时,不能抛出系统级额异常。(测试错误的处理逻辑是否符合预期)

L3:极端情况和边界数据可用。可能一开始无法考虑到很多边界条件和极端情况,所以这是一个需要长期维护的部分

L4:覆盖率达到100%

4个标准对应的运用场景:

 L1:实在时间紧迫并且代码对应的功能不是核心部分

 L2:非核心模块大部分时候应该要达到的标准

 L3:核心模块要达到的标准

 L4:全局基础框架、封装的非业务型类库要达到的标准

单元测试的数据从哪里来?

不能直连数据库,如果直连数据库,之前的逻辑错误所造成的数据错误,影响本次测试的成果。使用Mock对象

1:涉及到IO的代码和业务代码尽量分开。这里的IO不仅仅时磁盘IO还有网络IO。实现方式也很简单,将IO部分抽象出接口,通过依赖注入的方式调用。这样在写单元测试的时候

可以通过Mock方式来提供一个IO方法的实现。

2:测试数据与测试用例分离。在写单元测试的时候,因为需要考虑很多种情况,所以需要构造好几套测试数据。

@Test
void testAdd(){
        for(Object[] s : data()){
            assertEquals(s[2], (int)s[0]+(int)s[1]);
        }
}

public static Iterable<Object[]> data(){
            List<Object[]> list = new ArrayList<Object[]>();
            list.add(new Object[]{1,1,2});
            list.add(new Object[]{-1,1,0});
            list.add(new Object[]{0,0,0});
            return list;
}

  这样后续维护测试数据只要在data()方法里进行就好了,确保已发生的bug总是被覆盖在单元测试范围内。

原文地址:https://www.cnblogs.com/wangzuofei/p/13973006.html