Spring Boot单元测试详解
单元测试在日常项目开发中必不可少,Spring Boot 提供了完善的单元测试框架和工具用于测试开发的应用,本文将介绍 Spring Boot 为单元测试提供了哪些支持,以及如何在 Spring Boot 项目中进行单元测试。
下面通过示例演示 Spring Boot 是如何实现单元测试的。
示例代码如下:

图 1 单元测试的运行结果
由图 1 可知,单元测试方法运行成功并输出相应的结果,同时 IDEA 也会显示运行的所有单元测试结果,包括测试是否通过、运行时间、测试总数和成功次数等。
以上示例中的测试方法只是 spring-boot-starter-test 组件中的一部分功能,Spring Boot 自带的 spring-boot-starter-test 框架对测试的支持非常完善,包括 Web 请求测试、Service 方法测试等,后面会逐一介绍。

图 2 IDEA创建测试类界面
单击 OK 按钮,IDEA 会在 Test 目录下创建一个 UserServiceTest 测试类,并为勾选的测试类自动生成单元测试的方法。
执行单元测试也非常简单,只需将鼠标放在对应的方法上,右击并选择 Run 执行该方法即可。
MockMvc 能够模拟 HTTP 请求,使用网络的形式请求 Controller 中的方法,这样可以使得测试速度快、不依赖网络环境,而且它提供了一套完善的结果验证工具,测试和验证也非常简单、高效。
spring-boot-starter-test 具备强大的 Mock 能力,使用 @WebMvcTest 等注解实现模拟 HTTP 请求测试。下面通过示例演示如何测试 Controller 接口。
1) 创建 Controller 的测试类 HelloControllerTest,实现单元测试方法。示例代码如下:
示例代码说明如下:
2) 完成测试方法之后,执行测试方法:将鼠标放在对应的方法上,右击并选择 Run 执行该方法即可。可以看到输出如下:
如果接口有登录验证,则需要通过 MockHttpSession 注入用户登录信息,或者修改登录拦截器取消对单元测试的登录验证。
声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
Spring Boot集成单元测试
单元测试主要用于测试单个代码组件,以确保代码按预期方式工作。目前流行的有 JUnit 或 TestNG 等测试框架。Spring Boot 封装了单元测试组件 spring-boot-starter-test。下面通过示例演示 Spring Boot 是如何实现单元测试的。
1) 引入依赖
首先创建 Spring Boot 项目。在项目中引入 spring-boot-starter-test 组件,示例配置如下:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2) 创建单元测试
在 src/test 目录下新建一个 HelloTest 测试类,如果只想输出一句“Hello Spring Boot Test”,只需要用一个 @Test 注解即可。示例代码如下:
@SpringBootTest public class HelloTest { @Test public void hello(){ System.out.println("Hello Spring Boot Test"); } }在类的上面添加 @SpringBootTest 注解,系统会自动把这段程序加载到 Spring Boot 容器。@Test 注解表示该方法为单元测试方法。
3) 运行单元测试
单击 Run Test 或在方法上右击,再选择“Run 'hello'”,运行测试方法,运行结果如下图所示。
图 1 单元测试的运行结果
由图 1 可知,单元测试方法运行成功并输出相应的结果,同时 IDEA 也会显示运行的所有单元测试结果,包括测试是否通过、运行时间、测试总数和成功次数等。
以上示例中的测试方法只是 spring-boot-starter-test 组件中的一部分功能,Spring Boot 自带的 spring-boot-starter-test 框架对测试的支持非常完善,包括 Web 请求测试、Service 方法测试等,后面会逐一介绍。
测试Service方法
一般使用 Spring Boot 进行单元测试主要是针对 Service 和 API(Controller)进行。接下来通过示例演示 Spring Boot 如何测试 Service 方法。1) 创建Service测试类
创建 Service 测试类非常简单,使用 IDEA 可以一键自动创建单元测试类。首先,选择需要测试的 Service 类或方法,然后在对应的 Service 类中右击,选择Go To→Test→Create New Test
,打开如下图所示的创建测试类界面。
图 2 IDEA创建测试类界面
单击 OK 按钮,IDEA 会在 Test 目录下创建一个 UserServiceTest 测试类,并为勾选的测试类自动生成单元测试的方法。
2) 实现单元测试
在上面创建好的 UserServiceTest 类中会自动创建对应的单元测试方法,我们只需要在测试方法中实现对应的测试代码即可,具体的示例代码如下:@SpringBootTest public class UserServiceTest { @Autowired private UserService userService; @Test public void findOne() throws Exception { Assert.assertEquals("1002", userService.findOne()); } }如以上示例代码所示,在自动测试类上增加 @SpringBootTest 注解即可。首先注入需要测试的 Service,然后在单元测试中调用该方法,最后通过 Assert 断句判断返回结果是否正确。
执行单元测试也非常简单,只需将鼠标放在对应的方法上,右击并选择 Run 执行该方法即可。
测试Controller接口方法
上面是针对 Service 进行测试,但是有时需要对 API(Controller)进行测试,这时需要用到 MockMvc 类。MockMvc 能够模拟 HTTP 请求,使用网络的形式请求 Controller 中的方法,这样可以使得测试速度快、不依赖网络环境,而且它提供了一套完善的结果验证工具,测试和验证也非常简单、高效。
spring-boot-starter-test 具备强大的 Mock 能力,使用 @WebMvcTest 等注解实现模拟 HTTP 请求测试。下面通过示例演示如何测试 Controller 接口。
1) 创建 Controller 的测试类 HelloControllerTest,实现单元测试方法。示例代码如下:
@RunWith(SpringRunner.class) @WebMvcTest(HelloController.class) class HelloControllerTest { @Autowired private MockMvc mockMvc; @Test public void hello() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/hello") //执行一个请求 .contentType(MediaType.APPLICATION_JSON)) //接收的数据类型 .andExpect(status().isOk()) //添加执行完成后的断句,请求的状态响应码//是否为200,如果不是则测试不通过 .andDo(print()); //添加一个结果处理程序,表示要对结果进行处理,比如此处//使用print()输出整个响应结果信息 } }在上面的示例中,通过使用 MockMvc 构造一个 post 请求,MockMvcRequestBuilders 可以支持 post 和 get 请求,调用 print() 方法将请求和相应的过程都打印出来。
示例代码说明如下:
- MockMvcRequestBuilders.post("/hello"):构造一个 post 请求。
- contentType (MediaType.APPLICATION_JSON)):设置 JSON 返回编码,避免出现中文乱码的问题。
- andExpect(status().isOk()):执行完成后的断句,请求的状态响应码是否为 200,如果不是则测试不通过。
- andDo(print()):添加一个结果处理程序,表示要对结果进行处理,比如此处调用 print() 输出整个响应结果信息。
2) 完成测试方法之后,执行测试方法:将鼠标放在对应的方法上,右击并选择 Run 执行该方法即可。可以看到输出如下:
MockHttpServletRequest: HTTP Method = POST Request URI = /hello Parameters = {} Headers = [Content-Type:"application/json;charset=UTF-8"] Body = null Session Attrs = {} Handler: Type = com.weiz.helloworld.web.HelloController Method = com.weiz.helloworld.web.HelloController#hello() Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"17"] Content type = text/plain;charset=UTF-8 Body = hello Spring Boot Forwarded URL = null Redirected URL = null Cookies = []从上面的输出中可以看到,返回完整的 Http Response,包括 Status=200、Body = hello Spring Boot,说明接口请求成功并成功返回。
如果接口有登录验证,则需要通过 MockHttpSession 注入用户登录信息,或者修改登录拦截器取消对单元测试的登录验证。
常用的单元测试注解
在实际项目中,除了 @SpringBootTest、@Test 等注解之外,单元测试还有很多非常实用的注解,具体说明如下表所示。注解 | 说明 |
---|---|
@RunWith(SpringRunner.class) | 声明测试运行在 Spring 环境。SpringRunner 是 SpringJUnit4ClassRunner 的新名字,这样做仅仅是为了让名字看起来更简单一点。 |
@SpringBootTest | 用于 Spring Boot 应用测试,它默认会根据包名逐级往上找,一直找到 Spring Boot 主程序,通过类注解是否包含 @SpringBootApplication 来判断是否为主程序,并在测试时启动该类来创建 Spring 上下文环境。 |
@BeforeClass | 针对所有测试,只执行一次,并且必须为 static void。 |
@BeforeEach | 初始化方法,在当前测试类的每个测试方法前执行。 |
@Test | 测试方法,在这里可以测试期望异常和超时时间。 |
@AfterEach | 释放资源,在当前测试类的每个测试方法后执行。 |
@AfterClass | 针对所有测试,只执行一次,且必须为 static void。 |
@Ignore | 忽略的测试方法。 |
声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。