文章目录

1、加载测试专用属性2、加载测试专用配置3、测试类中启动web环境4、发送虚拟请求5、匹配(断言)响应的执行状态6、匹配响应的结果7、匹配响应头8、业务层测试事务回滚9、UT数据设置随机数据

1、加载测试专用属性

写单元测试时,如果需要一个临时属性,但不能影响其他代码(即作用范围是当前UT类),有两种方式实现:

方式一:使用@SpringBootTest注解的properties属性

模块配置中,有一个test.prop属性:

test:

prop: 9527

在UT中做临时修改:

@SpringBootTest(properties = {"test.prop=testValue1"})

public class PropertiesAndArgsTest {

@Value("${test.prop}")

private String msg;

@Test

void testProperties(){

System.out.println(msg);

}

}

以上这个写法:比多环境开发中的测试环境影响范围更小,仅对当前测试类有效。

方式二:使用args属性

在启动测试环境时可以通过args参数设置测试环境专用的传入参数:

@SpringBootTest(args = {"--test.prop=testValue2"})

public class PropertiesAndArgsTest {

@Value("${test.prop}")

private String msg;

@Test

void testProperties(){

System.out.println(msg);

}

}

以上这个args,就类比命令行参数启动、在启动类的args上赋值,–server.port=8080这个格式,第一种方式则类比properties文件,因此,当这两种方式同时设置一个属性时,args的方式优先级更高,生效。 以上这个加载测试临时属性,亮点是不影响其他UT或者其他模块代码,仅对当前测试类生效。

2、加载测试专用配置

源码中有一个Bean,定义了相关配置,如之前的MyBatisPlus的分页拦截器。那如何在UT里加一个配置Bean来辅助测试,且仅服务于这个UT类,如此,也不会引起配置冲突问题。先在test目录下定义一个配置Bean(肯定不能定义到com.src的实际源码里):

接下来使用@Import注解加载当前测试类专用的配置Bean

@SpringBootTest

@Import(MsgConfig.class)

public class ConfigurationTest {

@Autowired

private String msg;

@Test

void testConfiguration(){

System.out.println(msg);

}

}

3、测试类中启动web环境

平时写的测试Mapper和Service层方法的UT,就是一个普通的Java程序,没有web环境,想在web环境下启动,可以使用@SpringBootTest注解的webEnvironment属性。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

public class WebTest {

@Test

void testRandomPort () {

}

}

其中,属性取值可以为:使用源代码里定义的端口、随机端口、不启用web(默认)…

4、发送虚拟请求

在测试类中开启Web环境后,接下来在UT中直接测Controller层的接口:

开启虚拟MVC调用注入MockMvc对象创建虚拟对象,传入接口路径执行请求

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

//开启虚拟MVC调用

@AutoConfigureMockMvc

public class WebTest {

@Test

//注入虚拟MVC调用对象

public void testWeb(@Autowired MockMvc mvc) throws Exception {

//创建虚拟请求,当前访问/books

MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");

//执行请求

ResultActions action = mvc.perform(builder);

}

}

以上并不是一次正真的调用,而是虚拟出来了一套Web环境,在这个虚拟环境中发起了这次调用。记得加@AutoConfigureMockMvc开启需求Mvc调用,否则MockMvc这个Bean注入不上,至于注入写在形参里还是属性里,都行。

5、匹配(断言)响应的执行状态

在发送完虚拟请求调用接口后,接下来对请求响应的状态做一个匹配(断言):

获取执行结果定义执行状态匹配器定义预期状态对比预期状态和真实状态

@Test

public void testSataus(@Autowired MockMvc mvc) throws Exception {

MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books/1");

ResultActions action = mvc.perform(builder);

//匹配执行状态(是否预期值)

//定义执行状态匹配器

StatusResultMatchers status = MockMvcResultMatchers.status();

//定义预期执行状态

ResultMatcher ok = status.isOk();

//使用本次真实执行结果与预期结果进行比对

action.andExpect(ok);

}

写个不存在的路径,执行结果:

6、匹配响应的结果

和匹配状态一样,先看响应一个String的情况:

@Test

public void testSataus(@Autowired MockMvc mvc) throws Exception {

MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books/1");

ResultActions action = mvc.perform(builder);

//匹配执行结果(是否预期值)

//定义执行结果匹配器

ContentResultMatchers content = MockMvcResultMatchers.content();

//定义预期执行结果

ResultMatcher result = content.string("test1");

//使用本次真实执行结果与预期结果进行比对

action.andExpect(result);

}

当预期结果是一个json时:

ResultMatcher result = content.json("{\"id\":1,\"name\":\"SpringBoot2\"}");

7、匹配响应头

大同小异,步骤一致:

@Test

public void testContentType(@Autowired MockMvc mvc) throws Exception {

MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");

ResultActions action = mvc.perform(builder);

//匹配器

HeaderResultMatchers header = MockMvcResultMatchers.header();

//预期结果

ResultMatcher resultHeader = header.string("Content-Type", "application/json");

action.andExpect(resultHeader);

}

正常写UT时,这三个连一起就行,比如,先获取执行状态匹配器,再定义预期,然后做匹配。再响应头、响应结果…

8、业务层测试事务回滚

在UT时,不让方法执行给数据库带来脏数据,可以加事务注解@Transactional,在有@SpringBootTest注解的情况下,Spring会识别到我们在做UT而回滚事务。

@SpringBootTest

@Transactional

public class DaoTest {

@Autowired

private BookService bookService;

@Test

void testSave(){

bookservice.save(new Book());

}

}

如果想在测试用例中提交事务,可以通过@Rollback注解,并设置value属性为false:

@SpringBootTest

@Transactional

@Rollback(false) # 此时,会提交事务,即会影响数据库

public class DaoTest {

}

9、UT数据设置随机数据

测试用例数据通常采用随机值进行测试,使用SpringBoot提供的随机数为其赋值,举个例子:

testcast:

book:

id: ${random.int} # 随机整数

id2: ${random.int(10)} # 10以内随机数

type: ${random.int(10,20)} # 10到20随机数

uuid: ${random.uuid} # 随机uuid

name: ${random.value} # 随机字符串,MD5字符串,32位

publishTime: ${random.long} # 随机整数(long范围)

注意:

${random.int}表示随机整数${random.int(10)}表示10以内的随机数${random.int(10,20)}表示10到20的随机数其中表示范围的圆括号()可以是任意字符,例如[ ],!!均可

定义个实体类绑定下随机生成的数据:

测试类看下效果:

@Autowired

private Book book;

@Test

void testData(){

System.out.println(book);

}

写懵了,刚开始竟然直接输出了一个new的Book对象,对象于Bean,前者不受Spring管控,也就是说Spring拿到随机数据也不能赋值给它,这个对象必须是Bean,所以改为了自动注入。

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: