作者:又语

www.jianshu.com/p/4648fd55830e

本文介绍 Spring Boot 2 基于 JUnit 5 的单元测试实现方案。

目录

  • 简介

  • JUnit 4 和 JUnit 5 的差异

    • 忽略测试用例执行

    • RunWith 配置

    • @Before、@BeforeClass、@After、@AfterClass 被替换

  • 开发环境

  • 示例

简介

Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库,在 Spring Boot 2.2.0 版本之前,spring-boot-starter-test 包含了 JUnit 4 的依赖,Spring Boot 2.2.0 版本之后替换成了 Junit Jupiter。

JUnit 4 和 JUnit 5 的差异

1. 忽略测试用例执行

JUnit 4:

@Test
@Ignore
public void testMethod() {// ...
}

JUnit 5:

@Test
@Disabled("explanation")
public void testMethod() {// ...
}

2. RunWith 配置

JUnit 4:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Testpublic void contextLoads() {}
}

JUnit 5:

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class ApplicationTests {@Testpublic void contextLoads() {}
}

3. @Before、@BeforeClass、@After、@AfterClass 被替换

  • @BeforeEach 替换 @Before

  • @BeforeAll 替换 @BeforeClass

  • @AfterEach 替换 @After

  • @AfterAll 替换 @AfterClass

开发环境

  • JDK 8

示例

1.创建 Spring Boot 工程。

2.添加 spring-boot-starter-web 依赖,最终 pom.xml 如下。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.6.RELEASE</version><relativePath/></parent><groupId>tutorial.spring.boot</groupId><artifactId>spring-boot-junit5</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-boot-junit5</name><description>Demo project for Spring Boot Unit Test with JUnit 5</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.工程创建好之后自动生成了一个测试类。

package tutorial.spring.boot.junit5;import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class SpringBootJunit5ApplicationTests {@Testvoid contextLoads() {}}

这个测试类的作用是检查应用程序上下文是否可正常启动。@SpringBootTest 注解告诉 Spring Boot 查找带 @SpringBootApplication 注解的主配置类,并使用该类启动 Spring 应用程序上下文。Java知音公众号内回复“后端面试”, 送你一份Java面试题宝典

4.补充待测试应用逻辑代码

4.1. 定义 Service 层接口

package tutorial.spring.boot.junit5.service;public interface HelloService {String hello(String name);
}

4.2. 定义 Controller 层

package tutorial.spring.boot.junit5.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import tutorial.spring.boot.junit5.service.HelloService;@RestController
public class HelloController {private final HelloService helloService;public HelloController(HelloService helloService) {this.helloService = helloService;}@GetMapping("/hello/{name}")public String hello(@PathVariable("name") String name) {return helloService.hello(name);}
}

4.3. 定义 Service 层实现

package tutorial.spring.boot.junit5.service.impl;import org.springframework.stereotype.Service;
import tutorial.spring.boot.junit5.service.HelloService;@Service
public class HelloServiceImpl implements HelloService {@Overridepublic String hello(String name) {return "Hello, " + name;}
}

5.编写发送 HTTP 请求的单元测试。

package tutorial.spring.boot.junit5;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {@LocalServerPortprivate int port;@Autowiredprivate TestRestTemplate restTemplate;@Testpublic void testHello() {String requestResult = this.restTemplate.getForObject("http://127.0.0.1:" + port + "/hello/spring",String.class);Assertions.assertThat(requestResult).contains("Hello, spring");}
}

说明:

  • webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT 使用本地的一个随机端口启动服务;

  • @LocalServerPort 相当于 @Value("${local.server.port}");

  • 在配置了 webEnvironment 后,Spring Boot 会自动提供一个 TestRestTemplate 实例,可用于发送 HTTP 请求。

  • 除了使用 TestRestTemplate 实例发送 HTTP 请求外,还可以借助 org.springframework.test.web.servlet.MockMvc 完成类似功能,代码如下:

package tutorial.spring.boot.junit5.controller;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {@Autowiredprivate HelloController helloController;@Autowiredprivate MockMvc mockMvc;@Testpublic void testNotNull() {Assertions.assertThat(helloController).isNotNull();}@Testpublic void testHello() throws Exception {this.mockMvc.perform(MockMvcRequestBuilders.get("/hello/spring")).andDo(MockMvcResultHandlers.print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("Hello, spring"));}
}

以上测试方法属于整体测试,即将应用上下文全都启动起来,还有一种分层测试方法,譬如仅测试 Controller 层。

6.分层测试。

package tutorial.spring.boot.junit5.controller;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import tutorial.spring.boot.junit5.service.HelloService;@WebMvcTest
public class HelloControllerTest {@Autowiredprivate HelloController helloController;@Autowiredprivate MockMvc mockMvc;@MockBeanprivate HelloService helloService;@Testpublic void testNotNull() {Assertions.assertThat(helloController).isNotNull();}@Testpublic void testHello() throws Exception {Mockito.when(helloService.hello(Mockito.anyString())).thenReturn("Mock hello");this.mockMvc.perform(MockMvcRequestBuilders.get("/hello/spring")).andDo(MockMvcResultHandlers.print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().string("Mock hello"));}
}

说明:

@WebMvcTest 注释告诉 Spring Boot 仅实例化 Controller 层,而不去实例化整体上下文,还可以进一步指定仅实例化 Controller 层的某个实例:@WebMvcTest(HelloController.class);

因为只实例化了 Controller 层,所以依赖的 Service 层实例需要通过 @MockBean 创建,并通过 Mockito 的方法指定 Mock 出来的 Service 层实例在特定情况下方法调用时的返回结果。

琐碎时间想看一些技术文章,可以去公众号菜单栏翻一翻我分类好的内容,应该对部分童鞋有帮助。同时看的过程中发现问题欢迎留言指出,不胜感谢~。另外,有想多了解哪些方面内容的可以留言(什么时候,哪篇文章下留言都行),附菜单栏截图(PS:很多人不知道公众号菜单栏是什么)

END

我知道你 “在看”

有啥不同?来看看Spring Boot 基于 JUnit 5 实现单元测试相关推荐

  1. Spring BOOT ( 基于Kotlin 编程语言) 使用 Spring WebFlux 实现响应式编程

    Spring BOOT ( 基于Kotlin 编程语言) 使用 Spring WebFlux 实现响应式编程 image.png 参考文档:https://docs.spring.io/spring/ ...

  2. Spring boot基于redis实现附近的人(附源码下载)

    此文章是针对去年写的Java基于Redis实现"附近的人 进行业务优化! 核心源码 public class NearbyPO {@NotNull(message = "id值不能 ...

  3. (附源码)spring boot基于微信小程序的口腔诊所预约系统 毕业设计 201738

    小程序springboot口腔诊所预约系统 摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱, ...

  4. Spring Boot基于KLock实现分布式锁的使用详解(一)

    目录 一.背景 二.maven依赖 三.配置 3.1.单节点配置 3.2.集群配置 四.源码及使用 4.1.源码-Klock(<font color=#FF0000>核心注解</fo ...

  5. Spring boot基于itext实现定制化模板pdf生成功能

    最近被安排公司项目的一个活:根据给定的模板生成pdf,很多公司的项目涉及这种xxx单的生成,我这里是个检查单的生成,具体内容下面给出,和各位csdner一起分享学习一下,如有不对多多指教. 首先先看下 ...

  6. APP+spring boot基于Android智能手机的微课程学习系统设计与实现 毕业设计-附源码100909

    摘  要 随着现在网络的快速发展,网络的应用在各行各业当中它很快融入到了许多学校的眼球之中,他们利用网络来做这个微课程学习系统的网站,随之就产生了"智能手机的微课程学习系统 ",这 ...

  7. (附源码)APP+spring boot基于Android智能手机的微课程学习系统设计与实现 毕业设计100909

    摘  要 随着现在网络的快速发展,网络的应用在各行各业当中它很快融入到了许多学校的眼球之中,他们利用网络来做这个微课程学习系统的网站,随之就产生了"智能手机的微课程学习系统 ",这 ...

  8. APP+spring boot基于Android智能手机的微课程学习系统设计与实现 毕业设计源码100909

    摘  要 随着现在网络的快速发展,网络的应用在各行各业当中它很快融入到了许多学校的眼球之中,他们利用网络来做这个微课程学习系统的网站,随之就产生了"智能手机的微课程学习系统 ",这 ...

  9. Spring Boot——基于AOP的HTTP操作日志解决方案

    解决方案 package com.hailiu.web.aop;import com.fasterxml.jackson.databind.ObjectMapper; import com.haili ...

最新文章

  1. BI和大数据你能分清吗?
  2. ImageLoader must be init with configuration before using 错误解决方法
  3. java操作redis简单学习3
  4. web服务减少服务器TIME_WAIT
  5. 装了这几个插件后,我不得不给 IDEA 上个防沉迷
  6. eclipse中配置c++开发环境 Eclipse + CDT + MinGW
  7. Week 1:那些值得一阅的好文章
  8. 大数据学习笔记38:Hive - 内置函数(1)
  9. 血眼龙王萧沙传-翠花篇
  10. python实现web服务器_python实现web服务器
  11. Spark提交任务到集群
  12. c1flexGrid 在单元格中显示图片, 及行号
  13. 面试要求 熟悉linux系统,Linux面试中最常问的10个问题总结
  14. 小米笔记本bios版本大全_RedmiBook 14笔记本评测:初来乍到却熟路轻辙
  15. AOP之5种增强方法应用范例
  16. 防爆机器人布里茨还能买到吗_LOL防暴机器人 布里茨皮肤
  17. 【excel】如何绘制斜线表头
  18. C++编程:简易梯形面积计算器
  19. 一个人到过的12个国家,45座城市
  20. Vue项目设置ico

热门文章

  1. 被指抄袭后 新浪微博APP绿洲更换Logo 重新上架
  2. 来了!华为首款5G双模手机Mate 20 X (5G)发布:这个价格香吗?
  3. 同价位无敌?iQOO Neo配置曝光:骁龙845加持
  4. 小米9全面现货还降价,米粉却心情复杂?
  5. 苹果为提振销量疯狂试探!官网推出新福利:买买买更轻松
  6. 35岁的测试是测试的天花板吗?
  7. 队列阻塞_Java并发|阻塞队列ArrayBlockingQueue解析
  8. jmeter单线程读取csv_jmeter中如何使用csv文件并读取数据
  9. php html 目录列表,PHP获取文件目录列表
  10. 【Arthas】Arthas dump导出加载类