赞
踩
单元测试(Unit Test)是为了检验程序的正确性。一个单元可能是单个程序、类、对象、方法等,它是应用程序的最小可测试部件。SpringBoot提供了 spring-boot-starter-test 启动器。通过它,能引入一些有用的测试库。
(1)在SpringBoot中进行单元测试很简单,它已经自动添加好了Test的Starter依赖,如下:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
(2)只要在“src/test/java”目录下新建一个测试类即可,代码如下:
- import com.pjb.entity.UserInfo;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
-
- /**
- * 用户业务逻辑测试类(JUnit4)
- * @author pan_junbiao
- **/
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class UserServiceTest
- {
- @Autowired
- private UserService userService;
-
- @Before
- public void setUp()
- {
- }
-
- @After
- public void tearDown()
- {
- }
-
- @Test
- public void getUserInfoById()
- {
- //测试代码
- UserInfo userInfo = userService.getUserInfoById(1);
- }
- }

代码说明:
@SpringBootTest:是SpringBoot用于测试的注解,可指定入口类或测试环境等。
@RunWith(SpringRunner.class):让测试运行与Spring的测试环境。
@Test:表示为一个测试单元。
在单元测试中可能会产生垃圾数据,可以开启事务功能进行回滚——在方法或者类头部添加@Transactional注解即可,代码如下:
- /**
- * 新增员工
- * 加上@Transactional注解,开启事务
- * 这样测试执行完后就会进行回滚操作
- * @author pan_junbiao
- */
- @Test
- @Transactional
- public void addStaff()
- {
- //创建新用户信息
- UserInfo userInfo = new UserInfo();
- userInfo.setUserName("pan_junbiao的博客");
- userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- userInfo.setBlogRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行新增操作
- userDao.save(userInfo);
- }

JUnit5是对程序代码进行单元测试的Java框架。它用来编写自动化测试工具,降低测试的难度、减少烦琐性、并有效避免出现程序错误。
所有支持的注解都在包 org.junit.jupiter.api 下;
使用@Test、@TestTemplate、@RepeatedTest、@BeforeAll、@AfterAll、@BeforeEach或@AfterEach注释的方法不能返回值。
注解 | 说明 |
---|---|
@Test | 表示方法是测试方法。与JUnit 4的@Test注释不同,这个注释不声明任何属性,因为JUnit Jupiter中的测试扩展基于它们自己的专用注释进行操作。 |
@ParameterizedTest | 表示方法是参数化测试。 |
@RepeatedTest | 表示方法是重复测试的测试模板。 |
@TestFactory | 表示方法是动态测试的测试工厂。 |
@TestInstance | 用于为带注释的测试类配置测试实例生命周期。 |
@TestTemplate | 表示方法是为测试用例设计的模板,根据注册提供程序返回的调用上下文的数量进行多次调用。 |
@DisplayName | 声明测试类或测试方法的自定义显示名称。 |
@BeforeEach | 表示在当前类中每个@Test、@RepeatedTest、@ParameterizedTest或@TestFactory方法之前执行注释的方法;类似于JUnit 4的@Before。 |
@AfterEach | 表示在当前类中的每个@Test、@RepeatedTest、@ParameterizedTest或@TestFactory方法之后,都应该执行带注释的方法;类似于JUnit 4的@After。 |
@BeforeAll | 表示应在当前类中的所有@Test、@RepeatedTest、@ParameterizedTest和@TestFactory方法之前执行带注释的方法;类似于JUnit 4的@BeforeClass。 |
@AfterAll | 表示在当前类中,所有@Test、@RepeatedTest、@ParameterizedTest和@TestFactory方法都应该执行注释的方法;类似于JUnit 4的@AfterClass。 |
@Nested | 表示带注释的类是一个嵌套的、非静态的测试类。@BeforeAll和@AfterAll方法不能直接在 @Nested 测试类中使用,除非使用“每个类”测试实例生命周期。 |
@Tag | 用于在类或方法级别声明过滤测试的标记;类似于TestNG中的测试组或JUnit 4中的类别。 |
@Disabled | 用于禁用测试类或测试方法;类似于JUnit 4的@Ignore。 |
@ExtendWith | 用于注册自定义扩展。 |
JUnit5断言都是 org.junit.jupiter.api.Assertions 中的静态方法断言类。
Asser类中主要方法如下:
方法名称 | 方法描述 |
---|---|
assertEquals | 断言传入的预期值与实际值是相等的。 |
assertNotEquals | 断言传入的预期值与实际值是不相等的。 |
assertArayEquals | 断言传入的预期数组与实际数组是相等的。 |
assertNull | 断言传入的对象是为空。 |
assertNotNull | 断言传入的对象是不为空。 |
assertTrue | 断言条件为真。 |
assertFalse | 断言条件为假。 |
assertSame | 断言两个对象引用同一个对象,相当于"==”。 |
assertNotSame | 断言两个对象引用不同的对象,相当于"!=”。 |
assertThat | 断言实际值是否满足指定的条件。 |
【示例】SpringBoot 基于 JUnit5 的测试类。
- package com.pjb;
-
- import org.junit.jupiter.api.AfterEach;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
-
- /**
- * 用户业务逻辑测试类(JUnit5)
- * @author pan_junbiao
- **/
- @SpringBootTest
- public class UserServiceTest
- {
- @BeforeEach
- void setUp()
- {
- }
-
- @AfterEach
- void tearDown()
- {
- }
-
- @Autowired
- private UserService userService;
-
- @Test
- public void getUserInfoById()
- {
- //测试代码
- UserInfo userInfo = userService.getUserInfoById(1);
- }
- }

创建SpringBoot项目,实现Controller层、Service层、Dao层的单元测试。
Mockito是GitHub上使用最广泛的Mocking框架。它提供简洁的API来测试。Mockito简单易学、可读性强、验证语法简洁。
【示例】使用Mockito框架,对Controller层进行单元测试。
(1)创建UserController(用户信息控制器)。
- package com.pjb.controller;
-
- import com.pjb.entity.UserInfo;
- import com.pjb.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
- /**
- * 用户信息控制器
- * @author pan_junbiao
- **/
- @RestController
- @RequestMapping("user")
- public class UserController
- {
- @Autowired
- private UserService userService;
-
- /**
- * 获取用户信息
- * RESTful接口
- */
- @RequestMapping(value = "/{id}", method = RequestMethod.GET)
- public UserInfo getUserInfo(@PathVariable("id")int userId)
- {
- UserInfo userInfo = userService.getUserInfoById(userId);
- return userInfo;
- }
-
- /**
- * 根据用户ID,获取用户信息
- */
- @RequestMapping("/getUserInfoById")
- public UserInfo getUserInfoById(@RequestParam(value = "user_id", defaultValue = "0") int userId)
- {
- UserInfo userInfo = userService.getUserInfoById(userId);
- return userInfo;
- }
-
- /**
- * 新增用户信息
- * 参数:接收对象型参数
- */
- @RequestMapping(value = "/addUserByEntity", method = RequestMethod.POST)
- public boolean addUserByEntity(@RequestBody UserInfo userInfo)
- {
- boolean result = userService.addUser(userInfo);
- return result;
- }
-
- /**
- * 新增用户信息
- * 参数:接收多个参数
- */
- @RequestMapping(value = "/addUserByParam", method = RequestMethod.POST)
- public boolean addUserByParam(String userName,String blogUrl,String blogRemark)
- {
- UserInfo userInfo = new UserInfo();
- userInfo.setUserName(userName);
- userInfo.setBlogUrl(blogUrl);
- userInfo.setBlogRemark(blogRemark);
-
- boolean result = userService.addUser(userInfo);
- return result;
- }
- }

(2)实现Controller层的单元测试。
- package com.pjb.controller;
-
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.pjb.entity.UserInfo;
- import org.junit.Assert;
- import org.junit.jupiter.api.AfterEach;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.http.MediaType;
- import org.springframework.test.context.junit4.SpringRunner;
- import org.springframework.test.web.servlet.MockMvc;
- import org.springframework.test.web.servlet.MvcResult;
- import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
- import org.springframework.test.web.servlet.setup.MockMvcBuilders;
- import org.springframework.util.LinkedMultiValueMap;
- import org.springframework.util.MultiValueMap;
- import org.springframework.web.context.WebApplicationContext;
-
- /**
- * 用户信息控制器测试类
- * @author pan_junbiao
- **/
- @SpringBootTest
- @RunWith(SpringRunner.class)
- class UserControllerTest
- {
- //启用Web上下文
- @Autowired
- private WebApplicationContext webApplicationContext;
-
- private MockMvc mockMvc;
-
- @BeforeEach
- private void setUp()
- {
- //使用上下文构建MockMvc
- mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
- }
-
- @AfterEach
- private void tearDown()
- {
- }
-
- /**
- * 根据用户ID,获取用户信息
- * RESTful接口
- */
- @Test
- public void getUserInfo() throws Exception
- {
- //执行请求(使用GET请求,RESTful接口)
- MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}",1).accept(MediaType.APPLICATION_JSON_UTF8)).andReturn();
-
- //获取返回编码
- int status = mvcResult.getResponse().getStatus();
-
- //获取返回结果
- String content = mvcResult.getResponse().getContentAsString();
-
- //断言,判断返回编码是否正确
- Assert.assertEquals(200,status);
-
- //将JSON转换为对象
- ObjectMapper mapper = new ObjectMapper();
- UserInfo userInfo = mapper.readValue(content, UserInfo.class);
-
- //打印结果
- System.out.println("用户ID:" + userInfo.getUserId());
- System.out.println("用户姓名:" + userInfo.getUserName());
- System.out.println("博客地址:" + userInfo.getBlogUrl());
- System.out.println("博客信息:" + userInfo.getBlogRemark());
- }
-
- /**
- * 根据用户ID,获取用户信息
- * 使用GET请求
- */
- @Test
- public void getUserInfoById() throws Exception
- {
- //执行请求(使用GET请求)
- MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/user/getUserInfoById").param("user_id","1").accept(MediaType.APPLICATION_JSON_UTF8)).andReturn();
-
- //获取返回编码
- int status = mvcResult.getResponse().getStatus();
-
- //获取返回结果
- String content = mvcResult.getResponse().getContentAsString();
-
- //断言,判断返回编码是否正确
- Assert.assertEquals(200,status);
-
- //将JSON转换为对象
- ObjectMapper mapper = new ObjectMapper();
- UserInfo userInfo = mapper.readValue(content, UserInfo.class);
-
- //打印结果
- System.out.println("用户ID:" + userInfo.getUserId());
- System.out.println("用户姓名:" + userInfo.getUserName());
- System.out.println("博客地址:" + userInfo.getBlogUrl());
- System.out.println("博客信息:" + userInfo.getBlogRemark());
- }
-
- /**
- * 新增用户信息
- * 使用POST请求,传递对象型参数
- */
- @Test
- public void addUserByEntity() throws Exception
- {
- //创建新用户
- UserInfo userParam = new UserInfo();
- userParam.setUserName("pan_junbiao的博客");
- userParam.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- userParam.setBlogRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //将参数转换成JSON对象
- ObjectMapper mapper = new ObjectMapper();
- String json = mapper.writeValueAsString(userParam);
-
- //执行请求(使用POST请求,传递对象参数)
- MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/addUserByEntity").content(json).contentType(MediaType.APPLICATION_JSON)).andReturn();
-
- //获取返回编码
- int status = mvcResult.getResponse().getStatus();
-
- //获取返回结果
- String content = mvcResult.getResponse().getContentAsString();
-
- //断言,判断返回编码是否正确
- Assert.assertEquals(200,status);
-
- //断言,判断返回结果是否正确
- Assert.assertEquals("true",content);
- }
-
- /**
- * 多个参数的传递
- * 使用POST请求,传递多个参数
- */
- @Test
- public void addUserByParam() throws Exception
- {
- //多个参数的传递
- MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
- params.add("userName","pan_junbiao的博客");
- params.add("blogUrl","https://blog.csdn.net/pan_junbiao");
- params.add("blogRemark","您好,欢迎访问 pan_junbiao的博客");
-
- //执行请求(使用POST请求,传递多个参数)
- MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/addUserByParam").params(params)).andReturn();
-
- //获取返回编码
- int status = mvcResult.getResponse().getStatus();
-
- //获取返回结果
- String content = mvcResult.getResponse().getContentAsString();
-
- //断言,判断返回编码是否正确
- Assert.assertEquals(200,status);
-
- //断言,判断返回结果是否正确
- Assert.assertEquals("true",content);
- }
- }

执行结果:
【示例】Service层进行单元测试,使用Assert方法进行断言结果。
- package com.pjb.service;
-
- import com.pjb.entity.UserInfo;
- import org.junit.Assert;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
-
- /**
- * 用户业务逻辑测试类
- * @author pan_junbiao
- **/
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class UserServiceTest
- {
- @Autowired
- private UserService userService;
-
- @Test
- public void getUserInfoById()
- {
- //获取用户信息
- UserInfo userInfo = userService.getUserInfoById(1);
-
- //断言
- Assert.assertEquals(1,userInfo.getUserId());
- Assert.assertEquals("pan_junbiao的博客",userInfo.getUserName());
- Assert.assertEquals("https://blog.csdn.net/pan_junbiao",userInfo.getBlogUrl());
- Assert.assertEquals("您好,欢迎访问 pan_junbiao的博客",userInfo.getBlogRemark());
- }
- }

【示例】Dao层进行单元测试,以及使用@Transactional注解进行回滚操作。
- import com.pjb.entity.UserInfo;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
- import org.springframework.transaction.annotation.Transactional;
-
- /**
- * 用户信息数据库访问测试类
- * @author pan_junbiao
- **/
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class UserDaoTest
- {
- @Autowired
- private UserDao userDao;
-
- /**
- * 新增员工
- * 加上@Transactional注解,开启事务
- * 这样测试执行完后就会进行回滚操作
- * @author pan_junbiao
- */
- @Test
- @Transactional
- public void addStaff()
- {
- //创建新用户信息
- UserInfo userInfo = new UserInfo();
- userInfo.setUserName("pan_junbiao的博客");
- userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
- userInfo.setBlogRemark("您好,欢迎访问 pan_junbiao的博客");
-
- //执行新增操作
- userDao.save(userInfo);
- }
- }

赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。