SpringBoot 单元测试

SpringBoot 测试相关(单元测试、性能测试)

SpringBoot的单元测试
  1. 加入pom依赖。

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

编写了一个简单的测试接口及编写对应的测试类

UnitTestService.java

复制代码
/**
 * 测试接口类
 * @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.java

复制代码
/**
 * 编写接口测试类
 * @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);
    }
}
  1. 运行右击,选择 run As --> Junit Test 或者需要debug时,选择Debug As --> Junit Test,运行即可。
RESTful API 单元测试

对于服务类而言,编写单元测试是相对简单的,只需要像控制层自动引入接口类一样。但编写控制层即RESTful API 单元测试时,一般上就需要利用Mock技术进行测试了。当然也可以使用像Swagger或者PostMan这样的api测试工具进行测试(或者使用RestTemplate测试也是可行的),它可进行自动化测试,关于Postman会在之后的章节进行更新,作者也没有过多研究过,也只是用到了它的最基本的发起http请求的功能,之后会整理相关资料的。

创建一个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的用法,此处就不举例了,大家可自行搜索下,比较本章节只是简单示例下用法~

  1. 鉴于每次编写控制层测试类时,都需要创建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测试类时,还需要继承此基类即可。

Junit常用注解说明

@Test 加在待测试的方法前面

@Before 带上@Test的方法执行前会执行该方法

@After 带上@Test的方法执行完毕后会执行该方法

@BeforeClass 加上这个注解,则该方法会第一个执行(在所有方法中),且方法要加上关键词static,是一个static方法

@AfterClass 加上这个注解,则该方法最后一个执行(在所有方法中),同样,方法要加上关键词static,是一个static方法

详细的使用,大家可自行谷歌下,毕竟常用的也就前面三个了,(┬_┬)

基于ContiPerf的性能测试

ContiPerf是一个轻量级的测试工具,基于JUnit 4 开发,可用于效率测试等。可以指定在线程数量和执行次数,通过限制最大时间和平均执行时间来进行性能测试。

性能测试示例

1.加入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所以替代了。这里只是简单提下,因为具体的也不是很清楚,也没有深入了解过。
@Rule
public ContiPerfRule contiPerfRule = new ContiPerfRule();

复制代码
/**
 * 编写接口测试类
 * @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);
	}
}

2.控制台会有性能报告,同时访问:target/contiperf-report/index.html,会有图表提示。控制台输出:

复制代码
cn.lqdev.learning.springboot.chapter13.service.UnitTestServiceTest.test
samples: 100
max:     403
average: 41.5
median:  15

测试报告:

注解参数说明

@PerfTest

invocations:执行次数n,与线程数量无关,默认值为1

threads:线程池数量n,并发执行n个线程

duration:重复地执行时间n,测试至少执行n毫秒

@Required

throughput:吞吐要求n,要求每秒至少执行n个测试

average:平均执行时间n,要求平均执行时间不超过n毫秒

max:最大执行时间n,要求最大的执行时间不超过n毫秒

totalTime:总执行时间n,要求总的执行时间不超过n毫秒

median:50%平均执行时间n,要求所有执行的50%测试平均执行时间不超过n毫秒

percentile90:90%平均执行时间n,要求所有执行的90%测试平均执行时间不超过n毫秒

percentile95:95%平均执行时间n,要求所有执行的95%测试平均执行时间不超过n毫秒

percentile99:99%平均执行时间n,要求所有执行的99%测试平均执行时间不超过n毫秒

percentiles:表达式"a:n,b:m",要求a%的测试不超过n毫秒,b%的测试不超过m毫秒

相关推荐
wb043072019 小时前
使用 Java 开发 MCP 服务并发布到 Maven 中央仓库完整指南
java·开发语言·spring boot·ai·maven
nbwenren10 小时前
Springboot中SLF4J详解
java·spring boot·后端
helx8211 小时前
SpringBoot中自定义Starter
java·spring boot·后端
rleS IONS12 小时前
SpringBoot获取bean的几种方式
java·spring boot·后端
lifewange12 小时前
Go语言-开源编程语言
开发语言·后端·golang
白毛大侠12 小时前
深入理解 Go:用户态和内核态
开发语言·后端·golang
R***z10113 小时前
Spring Boot 整合 MyBatis 与 PostgreSQL 实战指南
spring boot·postgresql·mybatis
王码码203513 小时前
Go语言中的数据库操作:从sqlx到ORM
后端·golang·go·接口
星辰_mya13 小时前
雪花算法和时区的关系
数据库·后端·面试·架构师
赵丙双14 小时前
spring boot AutoConfiguration.replacements 文件的作用
java·spring boot