当你点开这个连接,说明对测试用例并不陌生,不论是业务开发、中间件开发、以及专业的测试人员,利用测试用例的高效覆盖,来进一步保证发版前工程质量永远都是没法绕开的话题,昨天针对后端业务开发测试用例的整改专门开了个小会,下面将一些我的相关的想法记录下来,若是能所以帮助到其余人那将是一件美妙的事情。java
先来看一张图,了解下测试用例的书写都有怎样的痛点,或许你们都经历过,或是正在经历着。spring
一、测试用例是什么?数据库
这个问题看上去像是传统的提问套路,我认可的确是,不过它能来事、实用为什么不问?测试用例是什么,我想测试用例就是用来针对某个子方法或逻辑的测试代码,看上去像是废话,但实际在编写测试用例的时候是否想过咱们的测试用例是否是写成了集成测试?集成测试最大的弊端是不易维护,不论是后期对原有测试方法的修改仍是对用例自身的维护代价都是至关大的,固然对于一些程序主流程而言,若是本身没有自信或者是求安心的话是能够针对某个父方法进行必定逻辑上的集成测试,然而大多数状况是不须要的。后端
二、分层测试工具
测试分层(Dao、Service、Facade、Controller),针对每一层的具体特性进行有针对性的测试,Dao层的某些方法的测试的确不可避免的须要去启动必定的配置、链接数据库等。Service层用例应主测处理逻辑,Facade数据转换层测试的覆盖率不须要太大,Controller测试可用能调通就行,覆盖率也不须要太大。测试
三、加载慢?调用外部环境?依赖多?this
去除没有必要的容器加载(spring...)、对于外部环境的调用必定要mock掉(关于mock的三方有不少,好比mockito)、以及对于须要去链接数据库的(Dao层以上)方法也进行mock。编码
四、编码规范要方便测试用例的书写spa
对于逻辑复杂、分支条件多的方法要进行拆分、拆成多个子方法,每一个子方法只处理同一纬度的逻辑,这样测试起来清晰度高并且减小了测试用例编写的复杂性,对于逻辑维度上的流式执行方法,能够不用进行测试覆盖。测试用例测的是逻辑、是分支处理。在这里也就是父方法能够不用测试(固然万事不能绝对)。代理
At last 上一个测试用例(mock工具使用mockito)
@Test public void testUploadOrderDocument_xingngService() throws Exception { WmsOrderDocument wmsOrderDocument = Mockito.mock(WmsOrderDocument.class); when(bestConfig.getFacilityName(anyString())).thenReturn("TEST"); when(bestConfig.getOrganizationCode(anyString())).thenReturn("TEST"); when(uploadSalesOrderDocService.createOrUpdateSoDoc(any(WmsUploadSoDocVo.class))).thenReturn(new ExternalPackVo()); when(customerService.getTplCustomerInfo(anyString())).thenReturn(Mockito.mock(TplCustomerVO.class)); WmsResponse<String> response = bestWmsServiceImpl.uploadOrderDocumentByXingngService(wmsOrderDocument); Assert.assertTrue(response.isSuccess()); }
补充:mockito工具使用
public class GlinkOrderServiceTest { @InjectMocks private GlinkOrderServiceImpl glinkOrderService; @Mock private BestConfig bestConfig; @Before public void setup() throws Exception { /* *初始化测试用例类中由Mockito的注解标注的全部模拟对象 */ MockitoAnnotations.initMocks(this); /* *将模拟对象注入至对象中,因为@InjectMocks拿到的是对象实例而不是代理对象因此下面这句能够不用加,但若是 *是经过@Resource或者@Autowired对对象进行注入则下面这句是须要的 */ ReflectionTestUtils.setField(AopTargetUtils.getTarget(glinkOrderService),”bestConfig", bestConfig); } @Test public void testParseFacilityName() { String organizationCode = "EC_CA"; String facilityName = "USCA01"; when(bestConfig.getWarehouseCode(anyString(), anyString())).thenReturn(facilityName); String warehouseCode = glinkOrderService.parseFacilityName(organizationCode,facilityName); Assert.assertNotNull(warehouseCode); } }