前面写了这么多章节,都是经过浏览器访问的形式,进行接口方法访问进而验证方法的正确与否。显然在服务或者接口比较少时,这么作没有啥问题,但一旦一个项目稍微复杂或者接口方法比较多时,这么验证就有点不符合程序猿的
懒人
的特性了。因此这章节,讲述下SpringBoot
中的单元测试及基于Contiperf
压测工具进行性能测试相关方面的知识点。html
是指对软件中的最小可
测试单元
进行检查和验证。通常上在开发阶段或者程序发布时,都会利用像Maven
这样的打包工具进行打包前的测试,避免没必要要的bug程序被打包部署。java
题外话:在开发阶段,都应该要求编写单元测试,核心的模块还须要进行覆盖测试,覆盖率至少要95%以上。git
对于
java
开发者而言,Junit
应该无人不知了。因此SpringBoot
也是基于Junit
进行单位测试的。github
0.加入pom依赖。web
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
1.这里为了演示,编写了一个简单的测试接口及编写对应的测试类。spring
UnitTestService.javaapi
/** * 测试接口类 * @author oKong * */ public interface UnitTestService { public String process(String msg); }
实现类:UnitTestServiceImpl.java浏览器
@Service public class UnitTestServiceImpl implements UnitTestService{ /** * 为了测试,这里直接返回传入的值 */ @Override public String process(String msg) { // TODO Auto-generated method stub return msg; } }
测试类:UnitTestServiceTest.javaspringboot
题外话:我的建议,每一个测试类都应该和对应的被测试类包路径一致。同时测试类的名称是被测试的类名+Test,如本例所示的:微信
/** * 编写接口测试类 * @author oKong * */ @RunWith(SpringRunner.class) //SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。 @SpringBootTest public class UnitTestServiceTest { @Autowired UnitTestService testService; public void test() { String msg = "this is a test"; String result = testService.process(msg); //断言 是否和预期一致 Assert.assertEquals(msg, result); } }
run As
--> Junit Test
或者须要debug时,选择Debug As
--> Junit Test
,运行便可。3.至此,一个简单的单元测试就结束了。**简单来讲,写一个单元测试是容易的,但写好一个单元测试是难的。**毕竟,每一个程序猿都以为本身的代码是没有问题的,难道不是吗?哈哈!
对于服务类而言,编写单元测试是相对简单的,只须要像控制层自动引入接口类同样。但编写控制层即RESTful API 单元测试时,通常上就须要利用
Mock
技术进行测试了。固然也可使用像Swagger
或者PostMan
这样的api测试工具进行测试(或者使用RestTemplate
测试也是可行的),它可进行自动化测试,关于Postman
会在以后的章节进行更新,做者也没有过多研究过,也只是用到了它的最基本的发起http请求的功能,以后会整理相关资料的。
0.建立一个RESTful接口服务。
/** * 编写mock测试服务 * @author oKong * */ @RestController public class DemoController { @GetMapping("/mock") public String demo(String msg) { return msg; } }
1.编写对应测试类
@RunWith(SpringRunner.class) //SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。 //由于是mock测试,在实际开发过程当中,可指定其测试启动时为随机端口,避免了没必要要的端口冲突。 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) //测试单一接口时 ,也可利用注解@WebMvcTest 进行单一测试 //@WebMvcTest(DemoController.class) public class DemoControllerTest { //使用 WebMvcTest 时使用 //@autowired mockMvc 是可自动注入的。 //当直接使用SpringBootTest 会提示 注入失败 这里直接示例利用 MockMvcBuilders工具建立 //@Autowired MockMvc mockMvc; @Autowired WebApplicationContext wc; @Before public void beforeSetUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(wc).build(); } @Test public void testDemo() throws Exception { String msg = "this is a mock test"; MvcResult result = this.mockMvc.perform(get("/mock").param("msg", msg)).andDo(print()).andExpect(status().isOk()) .andReturn(); //断言 是否和预期相等 Assert.assertEquals(msg, result.getResponse().getContentAsString()); } }
2.运行右击,选择 run As
--> Junit Test
或者须要debug时,选择Debug As
--> Junit Test
,运行便可。(也能够看见每次启动测试时,每次端口号都是不一样的。)
2018-07-25 23:16:28.733 INFO 13000 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 59999 (http) 2018-07-25 23:16:28.754 INFO 13000 --- [ main] c.l.l.s.c.controller.DemoControllerTest : Started DemoControllerTest in 5.673 seconds (JVM running for 6.769)
因为配置了print()
这个ResultHandler
,因此控制台会打印相关参数信息。建议设置此属性,这样就算测试有问题,也能看下具体的参数信息。其余相关mock的用法,此处就不举例了,你们可自行搜索下,比较本章节只是简单示例下用法~
MockMvc
对象,故可建立一个基类,这样免得每次都写。BaseMockTest.java
/** * mock 基类 * @author oKong * */ public abstract class BaseMockTest { @Autowired private WebApplicationContext wc; protected MockMvc mockMvc; @Before public void beforeSetUp() { this.mockMvc = MockMvcBuilders.webAppContextSetup(wc).build(); } }
这样编写mock测试类时,还须要继承此基类便可。
详细的使用,你们可自行谷歌下,毕竟经常使用的也就前面三个了,(┬_┬)
ContiPerf是一个轻量级的测试工具,基于JUnit 4 开发,可用于效率测试等。能够指定在线程数量和执行次数,经过限制最大时间和平均执行时间来进行性能测试。
0.加入pom依赖包。
<dependency> <groupId>org.databene</groupId> <artifactId>contiperf</artifactId> <version>2.3.4</version> <scope>test</scope> </dependency>
1.改写UnitTestServiceTest
测试类,进入ContiPerfRule
。 题外话:@Rule
是Junit
提供的一个扩展接口注解,其接口类为:org.junit.rules.MethodRule
,注意在Junit5中,已经被TestRule
因此替代了。这里只是简单提下,由于具体的也不是很清楚,也没有深刻了解过。
/** * 编写接口测试类 * @author oKong * */ @RunWith(SpringRunner.class) //SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。 @SpringBootTest public class UnitTestServiceTest { @Autowired UnitTestService testService; //引入 ContiPerf 进行性能测试 @Rule public ContiPerfRule contiPerfRule = new ContiPerfRule(); @Test //10个线程 执行10次 @PerfTest(invocations = 100,threads = 10) public void test() { String msg = "this is a test"; String result = testService.process(msg); //断言 是否和预期一致 Assert.assertEquals(msg, result); } }
target/contiperf-report/index.html
,会有图表提示。控制台输出:
cn.lqdev.learning.springboot.chapter13.service.UnitTestServiceTest.test samples: 100 max: 403 average: 41.5 median: 15
测试报告:
@PerfTest
@Required
本章节主要是对
Junit
和ContiPerf
的使用简单的示例,像MockMvc
的详细用法并无深刻,你们可自行搜索下,毕竟我也用的很少呀。
目前互联网上不少大佬都有
SpringBoot
系列教程,若有雷同,请多多包涵了。本文是做者在电脑前一字一句敲的,每一步都是实践的。若文中有所错误之处,还望提出,谢谢。
499452441
lqdevOps
完整示例:chapter-13