本篇介绍Springboot单元测试的一些基本操作,有人说一个合格的程序员必须熟练使用单元测试,接下来我们一起在Springboot项目中整合Junit4单元测试。
本文使用idea工具构建Springboot2.0+SpringMvc+Thymeleaf+SpringDataJPA+MySql项目
GitHub地址:https://github.com/jwam/springbootJunit4.git
点击file-settings,如图按照顺序操作即可,我这里已经安装过了所以最后一步不会显示install按钮。
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <!--<scope>test</scope>-->
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>5.0.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-test</artifactId>
- <version>2.0.0.RELEASE</version>
- </dependency>
- package com.springboot.demo.controller;
-
- import com.springboot.demo.base.controller.BaseController;
- import com.springboot.demo.base.utils.StateParameter;
- import com.springboot.demo.entity.User;
- import com.springboot.demo.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.ModelMap;
- import org.springframework.util.StringUtils;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- import javax.servlet.http.HttpServletRequest;
- import java.util.Date;
- import java.util.List;
-
- /**
- * @ClassName: UserController
- * @Auther: zhangyingqi
- * @Date: 2018/8/27 17:30
- * @Description:
- */
- @Controller
- @RequestMapping(value="/user")
- public class UserController extends BaseController{
- @Autowired
- UserService userService;
-
- /**
- * @auther: zhangyingqi
- * @date: 17:37 2018/8/27
- * @param: [request, user]
- * @return: org.springframework.ui.ModelMap
- * @Description: 用户保存&更新
- */
- @RequestMapping(value="/add", method = RequestMethod.POST)
- @ResponseBody
- public ModelMap add(User user){
- try {
- if(StringUtils.isEmpty(user.getId())){
- user.setId(getUuid());
- }else{
- user.setUpdateDate(new Date());
- }
- userService.save(user);
- logger.info("保存成功");
- return getModelMap(StateParameter.SUCCESS, user, "保存成功");
- } catch (Exception e) {
- e.printStackTrace();
- return getModelMap(StateParameter.FAULT, null, "保存失败");
- }
- }
-
- /**
- * @auther: zhangyingqi
- * @date: 17:47 2018/8/27
- * @param: [id]
- * @return: org.springframework.ui.ModelMap
- * @Description: 删除用户
- */
- @RequestMapping(value="/delete", method = RequestMethod.GET)
- @ResponseBody
- public ModelMap delete(String id){
- try {
- User user = userService.findById(id);
- if(user==null){
- return getModelMap(StateParameter.FAULT, user, "找不到该用户");
- }
- userService.delete(user);
- logger.info("删除成功");
- return getModelMap(StateParameter.SUCCESS, null, "删除成功");
- } catch (Exception e) {
- e.printStackTrace();
- return getModelMap(StateParameter.FAULT, null, "删除失败");
- }
- }
-
- /**
- * @auther: zhangyingqi
- * @date: 17:47 2018/8/27
- * @param: [request]
- * @return: java.lang.String
- * @Description: 查询用户列表
- */
- @RequestMapping(value="/list")
- public String view(HttpServletRequest request){
- List<User> list = userService.findAll();
- request.setAttribute("list", list);
- logger.info("返回列表页面");
- return "/demoPage/listPage";
- }
-
- }
UserController类中用到的其他依赖都可以去我文章开始提供的GitHub地址下载,其实看过我之前文章的人应该都知道,最简单的办法就是直接下载demo了,当然你也可以自己编写一个controller类,在本篇中并没有特别要求。
当然不能少了实体类User.java,父类前几篇文章我都有写过,demo里也有,节省文本这里不再给出。
- package com.springboot.demo.entity;
-
- import lombok.Data;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.Table;
-
- /**
- * @ClassName: User
- * @Auther: zhangyingqi
- * @Date: 2018/8/27 17:17
- * @Description:
- */
- @Entity
- @Table(name = "user")
- @Data
- public class User extends BaseEntity{
- @Column(name = "name", length = 100)
- private String name;
-
- @Column(name = "age")
- private int age;
- }
另外还需要list方法返回的实际页面,在项目template下demoPage下新建listPage.html
- <!DOCTYPE html>
- <html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
- <head>
- <meta charset="UTF-8">
- <title>用户列表</title>
- </head>
- <body>
- <div>
- <table>
- <thead>
- <tr>
- <th>用户名称</th>
- <th>年龄</th>
- <th>创建时间</th>
- </tr>
- </thead>
- <tbody>
- <tr th:if="${list !=null}" th:each="item : ${list}">
- <td th:text="${item.name}"></td>
- <td th:text="${item.age}"></td>
- <td th:text="${#dates.format(item.create_date, ‘yyyy-MM-dd‘)}"></td>
- </tr>
- </tbody>
- </table>
- </div>
- </body>
- </html>
在UserController中按住alt+insert键,如图选择将自动生成测试类。
这时Junit工具将自动生成一个test目录,在同路径下生成同类名+Test组合名称UserControllerTest.java类,这就是自动生成的测试类。
我们改造这个测试类的内容
首先在类名上加入注解@RunWith和@SpringBootTest,后者需指定springboot启动类
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = DemoApplication.class)
- public class UserControllerTest {
-
- }
然后引入MockMvc对象及WebApplicationContext上下文,如果涉及业务的测试内容还需引入其他依赖,@Before表示在测试方法执行之前执行会该方法,所以我们在这里实例化mockmvc对象,这样后面就可以操作他了。
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = DemoApplication.class)
- public class UserControllerTest {
-
- /**
- * 模拟mvc测试对象
- */
- private MockMvc mockMvc;
-
- /**
- * web项目上下文
- */
- @Autowired
- private WebApplicationContext webApplicationContext;
-
- /**
- * 业务数据接口
- */
- @Autowired
- private UserService userService;
-
- /**
- * 所有测试方法执行之前执行该方法
- */
- @Before
- public void before() {
- //获取mockmvc对象实例
- mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
- }
-
- }
接下来我们编写测试代码,首先对UserController中的查询用户列表方法进行测试,方法头部需添加@Test注解,具体方法内容如下,使用MockMvcRequestBuilders模拟get请求,status接收返回状态,responseString接收返回的内容。Assert.assertEquals
为通用的判断测试执行结果方法,其中三个参数分别为:不一致时提示信息,预期得到结果,实际得到结果。
- @Test
- public void testPage() throws Exception {
- MvcResult mvcResult = mockMvc
- .perform(// 1
- MockMvcRequestBuilders.get("/user/list") // 2
- //.param("name","getList") // 3
- )
- .andReturn();// 4
-
- int status = mvcResult.getResponse().getStatus(); // 5
- String responseString = mvcResult.getResponse().getContentAsString(); // 6
-
- Assert.assertEquals("请求错误", 200, status); // 7
- Assert.assertEquals("返回结果不一致", "/demoPage/listPage", responseString); // 8
- }
接下来执行这个单元测试模块,IDEA自动检测到这是一个测试方法,我们直接点击方法左边的启动按钮即可,因为我已经执行过并且测试未通过,所以显示红色,本来是绿色。
如果执行成功会提示success,我这里提供的这个测试方法执行后是报失败的,具体原因是在列表页面获取不到实体中的create_date字段
做如下修改,将create_date改为createDate即可,所以我们可以看到,测试页面时会去渲染方法返回的整个html页面,如果有语法错误将会报错,测试执行失败。
- <tbody>
- <tr th:if="${list !=null}" th:each="item : ${list}">
- <td th:text="${item.name}"></td>
- <td th:text="${item.age}"></td>
- <td th:text="${#dates.format(item.create_date, ‘yyyy-MM-dd‘)}"></td>
- </tr>
- </tbody>
再次启动测试单元测试不再报错,但是依旧执行失败,提示“返回结果不一致”,我们点击结果对比发现返回结果有差异,所以未达到期望,直接返回了不一致时的提示信息,因此我们在测试返回页面时只需执行Assert.assertEquals("请求错误", 200, status); 即可,不必再判断返回期望。
注释掉返回结果预期判断之后执行测试成功。
那么返回结果预期判断怎么用呢,我们看下面的第二个测试删除用户方法,param可以添加传递的参数,预期结果为删除成功,我这里模拟了删除成功后的返回json数据,实际应用中可根据情况设定。
可以看到后台打印删除成功,同时单元测试执行通过。
本篇我通过Junit4单元测试对springboot项目的controller类进行测试,掌握基本的单元测试在springboot中整合的使用方法。
下面给出完整的pom包,推荐大家直接下载文首给出的demo,可以直接运行,方便又快捷。
- <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>com.springboot</groupId>
- <artifactId>springbootJunit4</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>war</packaging>
-
- <name>springbootJunit4</name>
- <description>Demo project for Spring Boot</description>
-
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.4.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- <!--<scope>provided</scope>-->
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-entitymanager</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>5.2.10.Final</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-mail</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-thymeleaf</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <!--<scope>test</scope>-->
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>5.0.4.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-test</artifactId>
- <version>2.0.0.RELEASE</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
-
- </project>
全文完,2018/8/30
原文地址:https://blog.csdn.net/zhulier1124/article/details/82228831
原文:https://www.cnblogs.com/jpfss/p/10950514.html