一、背景形容

在版本开发中,时间段大抵的划分为:需要,开发,测试;

  • 需要阶段:了解需要做好接口设计;
  • 开发阶段:实现性能开发和对接;
  • 测试上线:自测,提测,修复,上线;

实际上开发阶段两个外围的工作,开发和流程自测,自测的基本目标是为本人提前解决可能呈现的问题;如果短少自测和提测两个关键步骤,那么问题就会被传递给更多的用户,产生更多的资源耗费;

自测是于开发而言,提测是对业余的测试人员而言,如果尽可能在自测阶段就发现问题,并解决问题,那么一个问题就不会影响到团队合作上的更多人员,如果一个简略的问题回升到团队合作层面,很可能会导致问题自身被放大

工欲善其事必先利其器,开发如果要做好自测流程,学会应用工具提高效率是非常要害的,自测的关键在于发现问题和解决问题,所以抉择好用和高效的工具能够极大的升高自测的工夫耗费。

上面围绕几个本人开发过程中罕用的测试工具和伎俩,做简略的总结,不在于比照形式的好坏,存在即正当,在不同场景中对正当伎俩的抉择,疾速解决问题才是基本目标

二、PostMan工具

PostMan很罕用的接口测试工具,开发过程中疾速测试接口,功能强大并且简略不便,岂但能够单个接口测试,也能够对接口分块治理批量运行:

整体来说工具比拟好用,适应于开发阶段的接口疾速测试,或者在解决问题的过程中单个接口的测试,同时对测试参数有存储和记忆能力,这也是受欢迎的一大起因。

然而该工具不适应于简单的流程化测试,例如须要依据上次接口的响应报文做别离解决,或者下次申请须要填充某个接口响应的数据。

三、Swagger文档

Swagger治理接口文档,是当下服务中很罕用的组件,通过对接口和对象的简略正文,疾速生成接口形容信息,并且能够对接口发送申请,帮助调试,该文档在前后端联调中极大的提高效率。

接口文档的治理自身是一件麻烦事,接口通常会依据业务一直的调整,如果独自保护一份接口文档,须要付出很多工夫老本,并且容易出问题,利用swagger就能够防止这个问题。

借助swagger注解标记对象

@TableName("jt_activity")@ApiModel(value="流动PO对象", description="流动信息表【jt_activity】")public class Activity {    @ApiModelProperty(value = "主键ID")    @TableId(type = IdType.AUTO)    private Integer id;    @ApiModelProperty(value = "流动主题")    private String activityTitle;    @ApiModelProperty(value = "分割号码")    private String contactPhone;    @ApiModelProperty(value = "1线上、2线下")    private Integer isOnline;    @ApiModelProperty(value = "举办地址")    private String address;    @ApiModelProperty(value = "主办单位")    private String organizer;    @ApiModelProperty(value = "创立工夫")    private Date createTime;}

借助swagger注解标记接口

@Api(tags = "活动主体接口")@RestControllerpublic class ActivityWeb {    @Resource    private ActivityService activityService ;    @ApiOperation("新增流动")    @PostMapping("/activity")    public Integer save (@RequestBody Activity activity){        activityService.save(activity) ;        return activity.getId() ;    }    @ApiOperation("主键查问")    @GetMapping("/activity/{id}")    public Activity getById (@PathVariable("id") Integer id){        return activityService.getById(id) ;    }    @ApiOperation("批改流动")    @PutMapping("/activity")    public Boolean updateById (@RequestBody Activity activity){        return activityService.updateById(activity) ;    }}

通常来说,基于swagger注解标记接口类和办法上的入参和要害返参对象即可,这样能够防止再独自保护接口文档。

Swagger接口文档在开发的过程中更多是表演文档的角色,真正应用swagger去调试的接口也常是一些增删改查的简略接口,这个工具也同样不适应于简单流程的测试。

四、TestRestTemplate类

SpringBoot测试包中集成的测试API,须要依赖测试包,能够访问控制层接口,十分不便的实现交互过程:

Jar包依赖

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-test</artifactId>    <scope>test</scope></dependency>

应用案例

@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)public class ActivityTest01 {    protected static Logger logger = LoggerFactory.getLogger(ActivityTest01.class) ;    @Resource    private TestRestTemplate restTemplate;    private Activity activity = null ;    @Before    public void before (){        activity = restTemplate.getForObject("/activity/{id}", Activity.class,1);        logger.info("\n"+JSONUtil.toJsonPrettyStr(activity));    }    @Test    public void updateById (){        if (activity != null){            activity.setCreateTime(new Date());            activity.setOrganizer("One商家");            restTemplate.put("/activity",activity);        }    }    @After    public void after (){        activity = restTemplate.getForObject("/activity/{id}", Activity.class,1);        logger.info("\n"+JSONUtil.toJsonPrettyStr(activity));        activity = null ;    }}

在TestRestTemplate源码中能够发现,基于RestTemplate做封装,很多性能的实现都是调用RestTemplate办法。

用写代码的形式去实现接口测试,灵便度十分高,能够依据流程做定制开发,很适应于中等简单的场景测试,这里为什么这样形容,上面比照Http申请再细说。

五、Http申请模式

通过模仿接口的Http申请实现的形式,目前来说个人感觉灵便的最高的形式,先看简略的案例:

@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)public class ActivityTest03 {    protected static Logger logger = LoggerFactory.getLogger(ActivityTest03.class) ;    protected static String REQ_URL = "服务地址+端口";    @Test    public void testHttp (){        // 查问        String getRes = HttpUtil.get(REQ_URL+"activity/1");        logger.info("\n {} ",JSONUtil.toJsonPrettyStr(getRes));        Activity activity = JSONUtil.toBean(getRes, Activity.class) ;        // 新增        activity.setId(null);        activity.setOrganizer("Http商家");        String saveRes = HttpUtil.post(REQ_URL+"/activity",JSONUtil.toJsonStr(activity));        logger.info("\n {} ",saveRes);        // 更新        activity.setId(Integer.parseInt(saveRes));        activity.setOrganizer("Put商家");        String putRes = HttpRequest.put(REQ_URL+"/activity")                .body(JSONUtil.toJsonStr(activity)).execute().body();        logger.info("\n {} ",putRes);    }}

这种形式对于简单的业务流程来说十分好用,当然这里不排除集体习惯,在测试简单流程的时候,一个简略计划:

  • 用户信息:模仿http中token数据;
  • 业务流程:通过数据获取包装参数模型;
  • 独立服务治理,模仿并发场景;
  • 依据执行过程生成剖析数据后果;

对于简单业务流程的测试,每个节点的模仿都具备肯定的难度,通常在残缺的流程中波及到的服务和库表都是多个,并且申请链路简单,基于一个灵便的自动化流程,去测试残缺的链路,能够对效率有极大的晋升。

六、Service层测试

针对服务层的测试伎俩,其本意在于业务实现的逻辑测试:

@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)public class ActivityTest04 {    protected static Logger logger = LoggerFactory.getLogger(ActivityTest04.class) ;    @Autowired    private ActivityService activityService ;    @Test    public void testService (){        // 查问        Activity activity = activityService.getById(1) ;        // 新增        activity.setId(null);        activityService.save(activity) ;        // 批改        activity.setOrganizer("Ser商家");        activityService.updateById(activity) ;        // 删除        activityService.removeById(activity.getId()) ;    }}

该测试在理论的开发过程也并不罕用,偶然在于某个业务办法实现难度很大,用来针对性测试。

七、MockMvc形式

MockMvc同样是SpringBoot集成测试包提供的测试形式,通过对象的模仿,验证接口是否合乎预期:

@AutoConfigureMockMvc@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)public class ActivityTest02 {    protected static Logger logger = LoggerFactory.getLogger(ActivityTest02.class) ;    @Resource    private MockMvc mockMvc ;    private Activity activity = null ;    @Before    public void before () throws Exception {        ResultActions resultAction = mockMvc.perform(MockMvcRequestBuilders.get("/activity/{id}",1)) ;        MvcResult mvcResult = resultAction.andReturn() ;        String result = mvcResult.getResponse().getContentAsString();        activity = JSONUtil.toBean(result,Activity.class) ;    }    @Test    public void updateById () throws Exception {        activity.setId(null);        activity.setCreateTime(new Date());        activity.setOrganizer("One商家");        ResultActions resultAction = mockMvc.perform(MockMvcRequestBuilders.post("/activity")                                            .contentType(MediaType.APPLICATION_JSON)                                            .content(JSONUtil.toJsonStr(activity))) ;        MvcResult mvcResult = resultAction.andReturn() ;        String result = mvcResult.getResponse().getContentAsString();        activity.setId(Integer.parseInt(result));        logger.info("result : {} ",result);    }    @After    public void after () throws Exception {        activity.setCreateTime(new Date());        activity.setOrganizer("Update商家");        ResultActions resultAction = mockMvc.perform(MockMvcRequestBuilders.put("/activity")                .contentType(MediaType.APPLICATION_JSON)                .content(JSONUtil.toJsonStr(activity))) ;        MvcResult mvcResult = resultAction.andReturn() ;        String result = mvcResult.getResponse().getContentAsString();        logger.info("result : {} ",result);    }}

对于这种Mock类型的测试,十分业余,通常集体应用极少,临时没有Get到其精华思维。

八、Mockito测试

Mock属于十分业余和规范的测试伎俩,须要依赖powermock包:

<dependency>    <groupId>org.powermock</groupId>    <artifactId>powermock-core</artifactId>    <scope>test</scope></dependency><dependency>    <groupId>org.powermock</groupId>    <artifactId>powermock-api-mockito2</artifactId>    <scope>test</scope></dependency><dependency>    <groupId>org.powermock</groupId>    <artifactId>powermock-module-junit4</artifactId>    <scope>test</scope></dependency>

简略应用案例:

@RunWith(PowerMockRunner.class)@SpringBootTestpublic class ActivityTest05 {    @Test    public void testMock (){        Set mockSet = PowerMockito.mock(Set.class);        PowerMockito.when(mockSet.size()).thenReturn(10);        int actual = mockSet.size();        int expected = 15 ;        Assert.assertEquals("返回值不合乎预期",expected, actual);    }    @Test    public void testTitle (){        String expectTitle = "Mock主题" ;        Activity activity = PowerMockito.mock(Activity.class);        PowerMockito.when(activity.getMockTitle()).thenReturn(expectTitle);        String actualTitle = activity.getMockTitle();        Assert.assertNotEquals("主题相符", expectTitle, actualTitle);    }}

能够通过Mock形式,疾速模拟出简单的对象构造,以便构建测试方法,因为应用很少,同样集体临时没Get到点。

九、源代码地址

GitHub·地址https://github.com/cicadasmile/middle-ware-parentGitEE·地址https://gitee.com/cicadasmile/middle-ware-parent

浏览标签

【Java根底】【设计模式】【构造与算法】【Linux零碎】【数据库】

【分布式架构】【微服务】【大数据组件】【SpringBoot进阶】【Spring&Boot根底】

【数据分析】【技术导图】【 职场】