单元测试之--groovy的DSL测试

做为一个大型电商后台业务系统,系统的稳定性和可用性有很高的要求。良好以及高覆盖的单元测试是其中重要的一环。在平常项目开发中时常会思考如何才能更加低成本,可读性高以及维护性高的单元测试方式。java

目前负责的系统,做为一个衔接上下游的中间系统,有十分复杂的业务场景以及众多的RPC调用,一般一个域的系统单元测试就超过500个,因此在单元测试上历来没有中止过探索和优化。spring

RPC Mock
首先为了可以更好的完成RPC调用的mock,针对公司的RPC框架编写了一个对应的mock服务。 一、扩展SpringJUnitClassRunner,在createTest中初始化一个本地的RPC服务,同时执行了全部的RPC服务目标地址为本地 二、整合mockito实现对象的mock。mockito是java经常使用的mock框架,因此对于使用者来讲机会是零成本。框架

BeanMock
Mock只是解决了RPC调用的问题,可是对于测试过程当中不少的嵌套调用mock的场景,每每都是经过很复杂的反射方式实现。反射方式在实现上麻烦不说,最严重的就是反射设置了mock对象以后,在测试完成以后并无将mock对象还原回真实的值。因为整个测试都是使用同一个spring上下文(经过spring注解能够实现每次都是新的上下文,可是影响测试执行效率),致使其余单元测试失败。而且这些单元测试失败的缘由都是十分难排查的。工具

事实上一些其余的mock组件可以实现private的mock,甚至是静态对象的mock,好比power mock。 但基于整个团队二三十人都是使用mockito的状况下,转为使用另一个mock组件,无言之间引入了新的使用以及维护成本。因此为了解决这个问题,基于spring的bean的特性,实现了Bean Mock,经过注解就能实现对嵌套对象的mock,十分简洁。详细介绍参见:BeanMock的使用介绍与说明单元测试

使用Groovy编写类DSL的单元测试
上面的两个Mock都是解决了单元测试过程当中的mock问题,除了对象的mock以外,单元测试更多的工做是在测试数据的构造,场景的模拟以及最终执行结果的断言验证。这个时候groovy的语言特性以及其对java的无缝结合就派上用场。 同时参加平常项目的QA用例评审过程当中,是对一个个业务场景的设计。这些测试用例能够看做特定的领域语言来描述特定的业务场景。测试

好比对于电商平台库存扣减的场景来讲,从订单库存领域,描述一个典型的业务场景以下:优化

一个订单,购买两个sku。其中一个是A库存,须要3件;另一个是B库存,须要2件。库存都占用成功。 执行订单库存扣减,验证结果:订单库存占用成功,占用明细有3个。占用明细1:占用数2 …设计

经过Groovy的语言特性,能够编写基于上面这个特定的领域语言,经过DSL的方式来进行单元测试,代码实例以下:code

@Test 
 void testSingleOrderJit() throws OspException { 
     makeRequest { 
         header { 
             detailList { 
                 [invType: Inv.A ] 
             } 
         } 
     }withOccupy OccupancyResult.success execute{ 
         oimsService.allocateOccupancy(it) 
     } verify{ 
         validateHeader { 
             [status:3, detailNum:1] 
         } 
         validateDetail { 
             [occupancyQty:-10, isShortAlloc:2] 
             } 
         } 
     }
}

从上面的代码看出,Groovy的语言特性在测试数据的构造以及断言上,相比java语言更为清晰与简洁。对象

示例中试图经过定义:

  1. makeRequest
  2. withInv
  3. withBrand
  4. withOccupancy

这样的领域名词帮助测试数据的模拟。好比在示例中就使用makeRequest建立了一个订单,有一个明细,明细是Inv.A的库存。经过withOccupancy来模拟这些库存都是能占用成功的。

经过定义execute,在execute中触发所要测试的业务方法

经过定义:

  1. verify
  2. verifyHeader
  3. verifyDetail

领域名词来帮助执行业务方法执行的结果验证。

上述的例子是一个很简单的DSL语言用法,但愿经过逐渐完善领域的DSL,让单元测试(其实这个阶段在不少人看来属于功能测试的范畴)具备可描述的特性。更加可以表达单元测试的意图,从各类数据构造和测试验证的场景中抽离出来,专一于要验证的结果。

固然,这个并不能适用于全部的单元测试场景,应该结合实际的场景和测试目选择合适的工具。这里目的是为了提供一种思路做为参考

相关文章
相关标签/搜索