Springboot08-项目单元测试(接口测试)

前言

  1-本文重点在于源码层面,分析Springboot单元测试的使用,对于其中的注解、方法等,不会仔细分析;

  2-本文项目实例相关配置:Java-1.8;  Springboot-1.5.12.RELEASE,使用的是Intellij

正文

1- JUnitGenerator V2.0 单元测试代码自动生成插件的使用

因为插件的安装和使用,比较简单,见参考资料-1,或自行百度;这里不再赘述;

注意:JUnitGenerator主要是可以针对需要测试的类,在test目录下快速生成对应的测试类,而测试的具体实现还是要手动处理;

2-最简单的单元测试,源码如下:

package com.hs.web.controller.system.login;
import net.sf.json.JSONObject;@RunWith(SpringRunner.class)
@SpringBootTest(classes= FrameworkApplication.class)
public class LoginControllerTest {private MockMvc mvc;@Autowiredprivate WebApplicationContext context;@Beforepublic void setUp() throws Exception {mvc = MockMvcBuilders.webAppContextSetup(context).build();}@Testpublic void login() throws Exception{//1-封装请求参数Map<String, String> paramMap = new HashMap<>();paramMap.put("openid", "tangyujie");JSONObject jsonObject = JSONObject.fromObject(paramMap);//2-构建请求RequestBuilder builder = MockMvcRequestBuilders.post("/api/shop/login").content(jsonObject.toString()).accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON);//3-执行请求
        mvc.perform(builder).andExpect(status().isOk()).andExpect(jsonPath("code").value(200)).andDo(MockMvcResultHandlers.print());}@Afterpublic void after(){}
}

如果只测试一个接口,或者只测试一个类,那么上面的方法基本上已经可以满足需求,但是针对上百个类或方法的情况,则会出现大量的代码冗余,并且还需要手动启动每一个测试类,这明显是不可取的;

所以,在上述简单的单元测试方法上,进行封装

3-封装通用的单元测试模板

单元测试模板可以满足如下需求:

  • 抽取公用的方法和注解,优化代码,实现代码复用,也方便维护
  • 多个单元测试类,一个启动入口,实现一键测试

接口测试的步骤

  1. 请求数据
  2. 构造请求
  3. 执行请求及判断请求结果
  4. 处理返回参数(本步骤可以没有)

备注:本项目的接口因为供App使用,(除了登录接口)其他都是要传token(跟在UTL?后面)

源码如下

测试模板目录

 BaseTest抽象类,用于封装通用方法

package com.hs.api.base;import net.sf.json.JSONObject;public abstract  class BaseTest {//1-1-构建post请求protected RequestBuilder getPostBuilder(String url, JSONObject jsonObject){RequestBuilder builder = MockMvcRequestBuilders.post(url).content(jsonObject.toString()).accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON);return builder;}//1-2-构建get请求protected RequestBuilder getGetBuilder(String url){RequestBuilder builder = MockMvcRequestBuilders.get(url).accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON);return builder;}//2-执行请求protected MvcResult performMVC(MockMvc mvc, RequestBuilder bulider ){try {MvcResult mvcResult = mvc.perform(bulider).andExpect(status().isOk()).andExpect(jsonPath("code").value(200))//.andDo(MockMvcResultHandlers.print())
                    .andReturn();return mvcResult;} catch (Exception e) {e.printStackTrace();return null;}}
}

BaseControllerTest类,继承 BaseTest抽象类,且是所有单元测试类的父类, 使用了@RunWith、@SpringBootTest等类注解,并且实现了通用的@Before和@After方法,以及登录接口的具体实现,主要是从普通的单元测试类中提取出公有的因素

package com.hs.api.base;
import net.sf.json.JSONObject;
//所有单元测试类的基类
@RunWith(SpringRunner.class)
@SpringBootTest(classes= FrameworkApplication.class)
@WebAppConfiguration
public abstract  class BaseControllerTest extends BaseTest {@Autowiredprotected WebApplicationContext context;protected MockMvc mvc ;protected  static String shopToken = null;//apptoken
@Beforeprotected void setUp() throws Exception {System.out.println("controller test is starting");mvc = MockMvcBuilders.webAppContextSetup(context).build();if(shopToken == null){System.out.println("获取shoptoken");shopToken = shopLogin();}}@Afterprotected void tearDown(){System.out.println("controller test is over");}//1-App登录操作protected String shopLogin() {//1-请求数据String url = "/api/shop/login";LoginReq loginReq = new LoginReq("tangyujie");JSONObject content = JSONObject.fromObject(loginReq);//2-构造请求RequestBuilder postBuilder = getPostBuilder(url, content);try {//3-执行请求-及判断请求结果MvcResult mvcResult = performMVC(mvc, postBuilder);//4-c处理返回参数,获取shopTokenString contentAsString = mvcResult.getResponse().getContentAsString();//System.out.println("contentAsString=== " + contentAsString);JSONObject jsonObject = JSONObject.fromObject(contentAsString);Map<String,Class<?>> classMap = new HashMap<String,Class<?>>();classMap.put("data", LoginRes.class);TestShopLoginRes entity = (TestShopLoginRes)JSONObject.toBean(jsonObject,TestShopLoginRes.class,classMap);//System.out.println("entity: " + entity);return entity .getData().getShopToken();} catch (Exception e) {e.printStackTrace();return null;}}}

ApiShopLoginControllerTest类,登录的接口的测试类,继承BaseControllerTest类;本类包含一个POST接口实例

package com.hs.api.shopapp.controller;public class ApiShopLoginControllerTest  extends BaseControllerTest{//POST请求示例//1-登录
    @Testpublic void loginOrRegister() {shopLogin();}
}

 ApiShopMemberControllerTest类,用户接口的测试类,继承BaseControllerTest类;本类包含一个GET接口实例

package com.hs.api.shopapp.controller;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;public class ApiShopMemberControllerTest extends BaseControllerTest{//GET请求示例
    @Testpublic void getMemberShopInfo() {//1-请求参数System.out.println("shopToken == " + shopToken);String url = "/api/shop/member/detail?shopToken=" + shopToken;//2-构建请求RequestBuilder getBuilder = getGetBuilder(url);try {//3-执行请求MvcResult mvcResult = performMVC(mvc, getBuilder);System.out.println("getMemberShopInfo mvcResult: " + mvcResult);} catch (Exception e) {e.printStackTrace();}}}

TestSuits类,本类没有具体的方法,唯一的作用是作为启动入口,测试全部测试类的方法

package com.hs.api;import org.junit.runner.RunWith;
import org.junit.runners.Suite;//单元测试总入口,在@Suite.SuiteClasses里面添加需要测试的测试类
@RunWith(Suite.class)
@Suite.SuiteClasses({ApiShopLoginControllerTest.class,ApiShopMemberControllerTest.class
})
public class TestSuits {
}

以下是模板用到的实体类POJO,主要是用户封装请求参数或返回参数,注意实体类和JSON字符串之间的转换

//请求参数实体类
public class LoginReq {private String openid;//openidpublic LoginReq() {}//省略geter和setter方法
}//返回参数实体父类
package com.hs.api.common;public class TestResponseEntity {public int code;public String message;public TestResponseEntity() {}//省略geter和setter方法
}
//登录接口返回参数实体类(两个,相互嵌套关系)public class TestShopLoginRes extends TestResponseEntity {private LoginRes data;public TestShopLoginRes() {}public TestShopLoginRes(LoginRes data) {this.data = data;}//省略geter和setter方法@Overridepublic String toString() {return "TestShopLoginRes{" +"data=" + data +'}';}
}public class LoginRes {private Long shopId;//
    private int mobileExistFlag;//手机号是否存在private String shopToken;//
    private int vipFlag;//是否是会员public LoginRes() {} //省略geter和setter方法@Overridepublic String toString() {return "LoginRes{" +"shopId=" + shopId +", mobileExistFlag=" + mobileExistFlag +", shopToken='" + shopToken + '\'' +", vipFlag=" + vipFlag +'}';}
}

以下是实例中测试的实际接口类

//登录接口类
@RestController
@RequestMapping(value="/api/shop/login")
public class ApiShopLoginController extends ApiShopBaseController {//1-登陆或注册@RequestMapping(value="",method = RequestMethod.POST,produces = {JSON_UTF8})public String loginOrRegister(@RequestBody LoginReq loginReqt){//省略业务
        }}//用户接口类

@RestController
@RequestMapping(value="/api/shop/member")
public class ApiShopMemberController extends ApiShopBaseController {//1-店主基本信息@RequestMapping(value = { "/detail" }, method={RequestMethod.GET},produces = {JSON_UTF8})public String getMemberShopInfo() throws ServerSqlErrorException {//省略业务
    }
}

参考文献:

1-JUnitGenerator使用方法:http://www.pianshen.com/article/516640707/

2-测试用例整合:https://blog.csdn.net/weixin_39800144/article/details/79241620

3-返回参数处理:https://blog.csdn.net/qq_16513911/article/details/83018027

转载于:https://www.cnblogs.com/wobuchifanqie/p/10445461.html

Springboot08-项目单元测试(接口测试)相关推荐

  1. 使用pytest对django项目单元测试

    2019独角兽企业重金招聘Python工程师标准>>> 背景 使用django开发了个人博客,欲单元测试,后遍寻网络,然相关资料甚少,遂成此文,望对汝有所助 环境 pytest py ...

  2. websocket导致spring boot 项目单元测试启动失败的问题解决

    背景 一个项目中需要实时的向前端展示数据变化,因此使用websocket.但是在项目中增加websocket后,功能没有问题,但是之前写的单元测试代码都无法运行.(代码和报错贴出来,如下,可以忽略) ...

  3. Spring Boot基础学习笔记02:Spring Boot项目单元测试、热部署与原理分析

    文章目录 零.学习目标 1.掌握Spring Boot单元测试实现 2.掌握Spring Boot热部署实现 3.熟悉Spring Boot基本原理 一.Spring Boot单元测试 (一)Spri ...

  4. Spring的maven项目单元测试报错 : Error:java:JDK isn't specified for module

    单元测试报错,跑不起来,报错如下: Error:java:JDK isn't specified for module 原来把  . idea 目录删除没有重启项目,重启项目 以后刷新maven: 点 ...

  5. 解读Android官方MVP项目单元测试

    Google在3月份推出了一个项目,用来介绍Android MVP架构的各种组合,可以认为是官方在这方面的最佳实践.令人称道的是除了MVP本身之外,这些工程配备了极其完善的单元测试用例,学习价值极高. ...

  6. 【30天学会接口自动化测试】接口自动化测试之实际项目做接口测试(6)

    整理了一些软件测试方面的资料.面试资料(接口自动化.web自动化.app自动化.性能安全.测试开发等),有需要的小伙伴可以文末加入我的学习交流qun,无套路自行领取~ 1.从实际项目出发分析测试结果处 ...

  7. springboot项目编写单元测试_SpringBoot项目单元测试(示例代码)

    前一段时间,有朋友问到springboot运用如何进行单元测试,结合LZ公司的实际运用,这里给大家描述一下三种单元测试的方式. 1.约定 单元测试代码写在src/test/java目录下 单元测试类命 ...

  8. SpringBoot 项目单元测试

    SpringBoot 单元测试方法 1.引入依赖 <dependency><groupId>org.springframework.boot</groupId>&l ...

  9. IDEA中Maven项目创建单元测试(JUnit4)

    文章目录 IDEA中Maven项目单元测试(JUnit4)记录 具体步骤 可能遇到的问题 后记 IDEA中Maven项目单元测试(JUnit4)记录 具体步骤 工具:idea2021.3版本,mave ...

最新文章

  1. linux获取近一小时日志,Linux分析日志获取最多访问的前10个IP
  2. JDK 10 的 109 项新特性
  3. JavaScript中的私有成员
  4. 2021暑假每日一题 【week2 完结】
  5. IHS Infonetics:网络运营商进军SDN
  6. 第7步 mybatis-generator dao层生成器
  7. JAVA中数字格式异常,java - Java数字格式异常 - 堆栈内存溢出
  8. 分析器错误信息: 未能加载类型命名空间.类... ---小结
  9. 小米10正式发布:3999元起!
  10. dva/dynamic
  11. github leaf项目怎么用_这份GitHub上价值49K的SpringBoot2+Thymeleaf企业应用实战,真香...
  12. 谷歌原数据保护团队技术主管:零信任实践分享
  13. 【BZOJ】【P3110】【ZJOI2013】【K大数查询】【题解】【树套树】
  14. 复旦大学高等代数学习指导书(白皮书)的评价
  15. 对透明表、簇表的理解
  16. 一键命令测试云主机的带宽
  17. mac 在调度中心关闭软件
  18. Cisco服务器http显示内容,IOS HTTP服务器的AAA控制
  19. qq浏览器HTML5在哪,qq浏览器wifi助手功能在哪里?
  20. 理论力学知识要点(九)

热门文章

  1. mysql数据库从删库到跑路之mysql完整性约束
  2. typedef 函数指针
  3. 敏捷开发中Scrum方法
  4. 只身单车游山东(五)
  5. 如何使用ElasTest实现测试的可观察性
  6. 分布式锁原理及实现方式
  7. JavaScript 工作原理之五-深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势(译)...
  8. 一分钟让你快速了解红外气体传感器作用,特性及应用
  9. SQL 解决从分组数据中总是挑选第一条数据的问题
  10. Azure上的VM代理及可扩展程序