之前把我的mall项目晋级到Spring Boot 2.7的时分,许多之前的测验办法都不能用了,原来是Spring Boot Test现已晋级支撑JUnit 5了。今日咱们来聊聊新版Spring Boot Test的运用,有了它,咱们就不需求再运用main办法来测验了!
SpringBoot实战电商项目mall(50k+star)地址:github.com/macrozheng/…
JUnit 简介
JUnit是一款Java语言的单元测验结构,现在大多数Java开发环境都现已支撑它了。JUnit测验也就是所谓的白盒测验,在程序员知道程序内部逻辑的基础上进行的测验,运用JUnit能让咱们快速地完结单元测验。Spring Boot Test将JUnit和其他测验结构结合起来,供给了快捷高效的测验手法,现在Spring Boot 2.7版本选用的是JUnit 5。
常用注解
在运用Spring Boot Test之前,咱们先来了解下它常用的注解,这对运用它很有协助,详细参考下表即可!
注解 | 作用 |
---|---|
@SpringBootTest | 用于指定测验类启用Spring Boot Test,默认会供给Mock环境 |
@ExtendWith | 假如只想启用Spring环境进行简略测验,不想启用Spring Boot环境,能够装备扩展为:SpringExtension |
@Test | 指定办法为测验办法 |
@TestMethodOrder | 用于装备测验类中办法的履行次序策略,装备为OrderAnnotation时,按@Order次序履行 |
@Order | 用于装备办法的履行次序,数字越低履行次序越高 |
@DisplayName | 用于指定测验类和测验办法的别名 |
@BeforeAll | 在测验类的一切测验办法前履行一次,可用于大局初始化 |
@AfterAll | 在测验类的一切测验办法后履行一次,可用于大局毁掉资源 |
@BeforeEach | 在测验类的每个测验办法前都履行一次 |
@AfterEach | 在测验类的每个测验办法后都履行一次 |
@Disabled | 禁用测验办法 |
@RepeatedTest | 指定测验办法重复履行 |
@ParameterizedTest | 指定参数化测验办法,相似重复履行,从@ValueSource中获取参数 |
@ValueSource | 用于参数化测验指定参数 |
@AutoConfigureMockMvc | 启用MockMvc的自动装备,可用于测验接口 |
根本运用
下面咱们来聊聊这些注解的根本运用,经过它们能够完成一些根本的单元测验。
集成Spring Boot Test
假如你想在项目中集成Spring Boot Test的话,需求先在pom.xml
中添加如下依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
最简略的测验
- 咱们先来一个最简略的单元测验,运用
@SpringBootTest
注解启用单元测验,运用@Test
指定测验办法,运用Assertions
类的办法来断语成果是否符合预期,详细代码如下。
/**
* JUnit根本测验
* Created by macro on 2022/10/11.
*/
@SpringBootTest
public class FirstTest {
@Test
public void test() {
int a=1;
Assertions.assertEquals(1,a);
}
}
- 然后点击测验办法左边按钮即可进行测验。
- 履行完结后咱们在IDEA的履行窗口中就能够看到办法测验经过了,因为运用
@SpringBootTest
启用了Spring Boot环境,日志中会输出Spring Boot的banner。
指定测验办法次序
- 咱们能够经过
@TestMethodOrder
注解和@Order
注解来指定一切测验办法的履行次序,详细代码如下。
/**
* JUnit指定办法测验次序
* Created by macro on 2022/10/10.
*/
@ExtendWith(SpringExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MethodOrderTest {
private static final Logger LOGGER = LoggerFactory.getLogger(MethodOrderTest.class);
@Test
@Order(1)
@DisplayName("order为1的办法")
void lowOrder(){
LOGGER.info("lowOrder method");
}
@Test
@Order(10)
@DisplayName("order为10的办法")
void highOrder(){
LOGGER.info("highOrder method");
}
}
- 点击类左边测验按钮,能够直接运转该类中的一切测验办法。
- 这儿因为咱们运用了
@DisplayName
注解给测验办法取了个别名,而且咱们运用了@ExtendWith
指定了运转环境为Spring而不是Spring Boot,所以日志中不会出现Spring Boot的banner,履行速度也更快。
生命周期测验
- 咱们还能够经过JUnit 5的生命周期注解来履行测验办法,比如在
@BeforeAll
注解指定的办法中做大局初始化,在@AfterAll
注解指定的办法中做资源的毁掉,详细代码如下。
/**
* JUnit生命周期测验
* Created by macro on 2022/10/10.
*/
@ExtendWith(SpringExtension.class)
public class LifecycleTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleTest.class);
@BeforeAll
static void allInit(){
LOGGER.info("allInit():在一切办法前履行,只履行一次");
}
@BeforeEach
void eachInit(){
LOGGER.info("eachInit():在测验办法前履行,每个测验办法前都履行");
}
@Test
void successTest() {
LOGGER.info("successTest():办法履行成功");
}
@AfterEach
void eachDown(){
LOGGER.info("eachDown():在测验办法后履行,每个测验办法后都履行");
}
@AfterAll
static void allDown(){
LOGGER.info("allDown():在测验办法后履行,每个测验办法后都履行");
}
}
- 测验完结后,控制台输出日志如下。
断语的运用
咱们能够经过
Assertions
类中供给的断语API来断语测验成果。
- 例如咱们能够运用
fail
办法直接断语办法履行失利并输出提示信息。
/**
* JUnit断语测验
* Created by macro on 2022/10/11.
*/
@ExtendWith(SpringExtension.class)
public class AssertTest {
@Test
void failTest() {
Assertions.fail("failTest():办法履行失利");
}
}
- 测验办法履行后会直接抛出异常信息。
- 还能够经过
assertTrue
、assertNull
、assertEquals
这类办法来断语成果是否符合预期。
/**
* JUnit断语测验
* Created by macro on 2022/10/11.
*/
@ExtendWith(SpringExtension.class)
public class AssertTest {
@Test
void failTest() {
Assertions.fail("failTest():办法履行失利");
}
@Test
void trueTest(){
Assertions.assertTrue(1==1);
}
@Test
void trueFalse(){
Assertions.assertFalse(3<=2);
}
@Test
void nullTest(){
String str = null;
Assertions.assertNull(str);
}
@Test
void notNullTest(){
String str = "test";
Assertions.assertNotNull(str);
}
@Test
void equalsTest(){
String str1 = "test";
String str2 = "test";
Assertions.assertEquals(str1,str2);
}
@Test
void notEqualsTest(){
String str1 = "test";
String str2 = "test";
Assertions.assertNotEquals(str1,str2);
}
}
- 也能够运用
assertThrows
办法来断语办法中抛出的异常。
/**
* JUnit断语测验
* Created by macro on 2022/10/11.
*/
@ExtendWith(SpringExtension.class)
public class AssertTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleTest.class);
@Test
void throwsTest(){
Assertions.assertThrows(NullPointerException.class,()->{
String str = null;
LOGGER.info(str.toLowerCase());
});
}
}
- 还可经过
assertTimeout
办法断语办法的履行时间。
/**
* JUnit断语测验
* Created by macro on 2022/10/11.
*/
@ExtendWith(SpringExtension.class)
public class AssertTest {
@Test
void timeoutTest(){
Assertions.assertTimeout(Duration.ofMillis(1000),()->{
long sleepTime = 2000;
ThreadUtil.sleep(sleepTime);
LOGGER.info("timeoutTest():休眠{}毫秒",sleepTime);
});
}
}
- 或者经过
assertAll
办法将几个断语结合起来运用,Assertions
类中供给的工具办法许多,详细能够参考它的代码。
/**
* JUnit断语测验
* Created by macro on 2022/10/11.
*/
@ExtendWith(SpringExtension.class)
public class AssertTest {
@Test
void assertAllTest(){
Assertions.assertAll(()->{
trueTest();
},()->{
nullTest();
},()->{
equalsTest();
});
}
}
其他测验
- Spring Boot Test除了上述测验功用,还能够运用
@Disabled
来禁用某个测验办法。
/**
* JUnit其他测验
* Created by macro on 2022/10/10.
*/
@ExtendWith(SpringExtension.class)
public class OtherTest {
@Test
@Disabled("用于测验@Disabled注解")
void disabledTest() {
LOGGER.info("disabledTest():办法被履行");
}
}
- 也能够运用
@RepeatedTest
来完成循环测验。
/**
* JUnit其他测验
* Created by macro on 2022/10/10.
*/
@ExtendWith(SpringExtension.class)
public class OtherTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleTest.class);
private static int count = 0;
@RepeatedTest(3)
void repeatedTest() {
count++;
LOGGER.info("repeatedTest():重复履行第{}次",count);
}
}
- 还能够经过
@ParameterizedTest
来进行参数化测验。
/**
* JUnit其他测验
* Created by macro on 2022/10/10.
*/
@ExtendWith(SpringExtension.class)
public class OtherTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LifecycleTest.class);
@ParameterizedTest
@ValueSource(ints = {1,2,3})
public void parameterizedTest(int a){
LOGGER.info("parameterizedTest():a={}",a);
}
}
- 运转以上测验办法后,详细测验成果如下。
项目实战
上面介绍了Spring Boot Test的根本运用,下面咱们结合项目来运用下它。
Dao层测验
假如咱们的项目需求对数据拜访层Dao中的办法进行测验的话,直接注入Mapper接口,在测验办法中直接调用即可,这儿对根据ID查询品牌的Mapper办法进行测验。
/**
* Dao层办法测验
* Created by macro on 2022/10/11.
*/
@SpringBootTest
public class MapperTest {
private static final Logger LOGGER = LoggerFactory.getLogger(MapperTest.class);
@Autowired
private PmsBrandMapper brandMapper;
@Test
void testGetById(){
long id = 6;
PmsBrand pmsBrand = brandMapper.selectByPrimaryKey(id);
LOGGER.info("brand name:{}",pmsBrand.getName());
Assertions.assertEquals("小米",pmsBrand.getName());
}
}
Service层测验
对事务层Service中的办法测验也是一样的,直接注入Service接口,在测验办法中直接调用即可,这儿对根据ID查询品牌的Service办法进行测验。
/**
* Service层办法测验
* Created by macro on 2022/10/11.
*/
@SpringBootTest
public class ServiceTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTest.class);
@Autowired
private PmsBrandService brandService;
@Test
void testGetById(){
long id = 6;
PmsBrand pmsBrand = brandService.getBrand(id);
LOGGER.info("brand name:{}",pmsBrand.getName());
Assertions.assertEquals("小米",pmsBrand.getName());
}
}
Controller层测验
关于Controller层办法进行测验,有时咱们需求模仿恳求,运用MockMvc即可,这儿模仿测验下分页查询品牌列表的接口。
/**
* Controller层办法测验
* Created by macro on 2022/10/11.
*/
@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void mvcTest() throws Exception{
//模仿发送一个恳求拜访分页查询品牌列表的接口
mockMvc.perform(MockMvcRequestBuilders.get("/brand/list") //设置恳求地址
.param("pageNum","1") //设置恳求参数
.param("pageSize","5"))
.andExpect(MockMvcResultMatchers.status().isOk()) //断语返回状况码为200
.andDo(MockMvcResultHandlers.print()) //在控制台打印日志
.andReturn(); //返回恳求成果
}
}
因为咱们挑选了在控制台输出日志,控制台将输出如下信息。
总结
今日带大家体会了一把Spring Boot Test,作为Spring Boot官方测验结构,的确功用很强壮。因为其主要基于JUnit 5,和JUnit 5的用法根本一致。运用它进行单元测验,无需启动整个项目,更快更好用!
参考资料
JUnit 5官方文档:junit.org/junit5/docs…
项目源码地址
github.com/macrozheng/…