Spring Boot工程测试之使用MockMvc进行UT,达到覆盖每一行代码的目标

Spring Boot工程测试之使用MockMvc进行UT,达到覆盖每一行代码的目标,第1张

1. 背景

基于Spring Boot的项目,公司强制要求必须写UT,否则不让提MR,而且要覆盖每一行代码。

2. 问题

因为要覆盖每一行代码,考虑到有些功能使用到了filter或者interceptor,所以采用在测试类中直接注入controller类的方式也满足不了。
例如:

@Resource
private UserController userController;
public void testGetUser(){
	userController.getXX();
}
3. 解决办法

使用MockMvc,可以从头到尾,测试一遍,就类似用户直接使用系统的感觉,帮助开发者覆盖到filter->interceptor->controller->service->dao的每一行代码。

废话不说,直接上代码

4. 工程结构

4.1 工程pom文件

<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.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.5.11version>
        <relativePath/> 
    parent>
    <groupId>com.xywei.springbootgroupId>
    <artifactId>springtest-demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>springtest-demoname>
    <description>Demo project for Spring Boot with testdescription>
    <properties>
        <java.version>1.8java.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombokgroupId>
                            <artifactId>lombokartifactId>
                        exclude>
                    excludes>
                configuration>
            plugin>
        plugins>
    build>

project>

4.2 MockMvc之Get请求+请求头 4.2.1 controller方法
    /**
     * GET请求,查询参数+请求头
* 随机返回用户名和密码 * * @param userId * @param userToken * @return */
@GetMapping("/getUserById") public ResponseEntity<BaseResult> getUserById(@RequestParam(value = "user_id", required = true) String userId, @RequestHeader(value = "user_token") String userToken) { BaseResult<User> baseResult = new BaseResult<>(); User user = new User(userId, "whoami-" + userId.hashCode(), UUID.randomUUID().toString()); baseResult.setCode(HttpStatus.OK.value()); baseResult.setMessage(HttpStatus.OK.getReasonPhrase()); baseResult.setData(user); return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK); }
4.2.2 MockMvc测试
    @Test
    public void testGetUserById() {

        try {
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .get("/getUserById") // 相当于postman输入请求地址
                            .param("user_id", "userId:998") // 相当于postman输入查询参数
                            .header("user_token", "为人民服务")// 相当于postman输入headers信息
            );
            String result = perform.andExpect(MockMvcResultMatchers.status().isOk())
                    .andReturn().getResponse().getContentAsString();
            ObjectMapper objectMapper = new ObjectMapper();
            BaseResult baseResult = objectMapper.readValue(result, BaseResult.class);
            Assert.notNull(baseResult.getData(), "expect not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
4.3 MockMvc之POST请求+表单参数 4.3.1 controller方法
    /**
     * POST请求,接受表单参数
     * 给什么就返回什么,随机生成id
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/getUserByUsernamePassword")
    public ResponseEntity<BaseResult> getUserByUsernamePassword(String username, String password) {
        BaseResult<User> baseResult = new BaseResult<>();
        User user = new User(UUID.randomUUID().toString(), username, password);
        baseResult.setCode(HttpStatus.OK.value());
        baseResult.setMessage(HttpStatus.OK.getReasonPhrase());
        baseResult.setData(user);
        return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK);
    }
4.3.2 MockMvc测试
    @Test
    public void testGetUserByUsernamePassword() {
        try {
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .post("/getUserByUsernamePassword") // 相当于postman输入请求地址
                            .param("username", "吃了八年的鱼") // 相当于postman输入表单参数
                            .param("password", "我为群众办实事") // 相当于postman输入表单参数
            );
            String result = perform
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn().getResponse().getContentAsString();
            Assert.notNull(result, "should be not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
4.4 MockMvc之POST请求+JSON参数 4.4.1 controller方法
    /**
     * POST请求,接受JSON数据
     * 给什么就返回什么
     *
     * @param users
     * @return
     */
    @PostMapping("/insertUser")
    public ResponseEntity<BaseResult> insertUser(@RequestBody List<User> users) {
        BaseResult<List<User>> baseResult = new BaseResult<>();
        baseResult.setCode(HttpStatus.OK.value());
        baseResult.setMessage(HttpStatus.OK.getReasonPhrase());
        baseResult.setData(users);
        return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK);
    }

4.4.2 MockMvc测试
    @Test
    public void testInsertUser() {

        User user = new User(UUID.randomUUID().toString(), "群众第一", "为群众谋福利");
        List<User> param = new ArrayList<>();
        param.add(user);
        try {
            String jsonData = new ObjectMapper().writeValueAsString(param);
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .post("/insertUser") // 相当于postman输入请求地址
                            .contentType(MediaType.APPLICATION_JSON)
                            .content(jsonData)
            );
            String result = perform
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn().getResponse().getContentAsString();
            Assert.notNull(result, "should be not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
4.5 完整的Tests代码
package com.xywei.springboot.springtestdemo;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xywei.springboot.springtestdemo.entity.User;
import com.xywei.springboot.springtestdemo.vo.BaseResult;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
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 org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@SpringBootTest
@AutoConfigureMockMvc
public class UserTests {

    @Resource
    private MockMvc mockMvc;

    @Test
    public void testGetUserById() {

        try {
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .get("/getUserById") // 相当于postman输入请求地址
                            .param("user_id", "userId:998") // 相当于postman输入查询参数
                            .header("user_token", "为人民服务")// 相当于postman输入headers信息
            );
            String result = perform.andExpect(MockMvcResultMatchers.status().isOk())
                    .andReturn().getResponse().getContentAsString();
            ObjectMapper objectMapper = new ObjectMapper();
            BaseResult baseResult = objectMapper.readValue(result, BaseResult.class);
            Assert.notNull(baseResult.getData(), "expect not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Test
    public void testGetUserByUsernamePassword() {
        try {
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .post("/getUserByUsernamePassword") // 相当于postman输入请求地址
                            .param("username", "吃了八年的鱼") // 相当于postman输入表单参数
                            .param("password", "我为群众办实事") // 相当于postman输入表单参数
            );
            String result = perform
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn().getResponse().getContentAsString();
            Assert.notNull(result, "should be not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testInsertUser() {

        User user = new User(UUID.randomUUID().toString(), "群众第一", "为群众谋福利");
        List<User> param = new ArrayList<>();
        param.add(user);
        try {
            String jsonData = new ObjectMapper().writeValueAsString(param);
            ResultActions perform = mockMvc.perform(
                    MockMvcRequestBuilders
                            .post("/insertUser") // 相当于postman输入请求地址
                            .contentType(MediaType.APPLICATION_JSON)
                            .content(jsonData)
            );
            String result = perform
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn().getResponse().getContentAsString();
            Assert.notNull(result, "should be not empty!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

5 总结
  1. 已上代码基于所有大佬都有基础的条件,如有不懂,请自行查阅SpringBoot的使用。
  2. 代码中的Filter和Inteceptor太简单,所以没有给出,请自行配置,更好体验MockMvc。
  3. 未连接数据库,请自行配置。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/756449.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存