Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何对Spring MVC中的Controller进行单元测试

如何对Spring MVC中的Controller进行单元测试

作者头像
编程随笔
发布于 2022-04-29 04:20:35
发布于 2022-04-29 04:20:35
2.5K00
代码可运行
举报
文章被收录于专栏:后端开发随笔后端开发随笔
运行总次数:0
代码可运行

对Controller进行单元测试是Spring框架原生就支持的能力,它可以模拟HTTP客户端发起对服务地址的请求,可以不用借助于诸如Postman这样的外部工具就能完成对接口的测试。 具体来讲,是由Spring框架中的spring-test模块提供的实现,详见MockMvc

如下将详细阐述如何使用MockMvc测试框架实现对“Spring Controller”进行单元测试,基于Spring Boot开发框架进行验证。 添加测试框架依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- Spring框架 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
!<-- Spring测试框架 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!-- 文件操作工具 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

导入静态工具方法

为了便于在编写测试用例时直接调用测试框架自带的静态方法,首先需要导入这些静态工具方法。 需要导入的静态方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.setup.SharedHttpSessionConfigurer.*;

初始化MockMvc

初始化MockMvc有2种方式: 方式1:明确指定需要测试的“Controller”类进行配置 方式2:基于Spring容器进行配置,包含了Spring MVC环境和所有“Controller”类,通常使用这种方式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootTest
public class TestControllerTest {

    MockMvc mockMvc;

    // 初始化MockMvc
    @BeforeEach
    void setUp(WebApplicationContext wac) {
        // 方式1:明确指定需要测试的“Controller”类
        this.mockMvc = MockMvcBuilders.standaloneSetup(new TestController()).build();

        // 方式2:基于Spring容器进行配置,包含了Spring MVC环境和所有“Controller”类。
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
}

另外,还可以对MockMvc进行全局配置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 全局配置MockMvc
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
        .defaultRequest(get("/").accept(MediaType.APPLICATION_JSON)) // 默认请求路径
        .apply(sharedHttpSession()) // 配置session
        .alwaysExpect(status().isOk()) // 预期响应状态码
        .alwaysExpect(content().contentType("application/json;charset=UTF-8")) // 预期内容类型
        .build();

执行测试

MockMvc支持对常见的HTTP方法,如:GET,POST,PUT,DELETE等,甚至还支持文件上传请求。

测试GET接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 访问GET接口:不带参数
@Test
public void testSimpleGet() throws Exception {
    MvcResult result = this.mockMvc.perform(get("/test/simple/get")
            .accept(MediaType.APPLICATION_JSON)) // 接受JSON格式响应消息
            .andReturn(); // 获取返回结果
    Assertions.assertEquals("OK", result.getResponse().getContentAsString());
}

// 访问GET接口:带URL参数
@Test
public void testParamGet() throws Exception {
    int id = 10;
    // 方式1:在URI模板中指定参数
    //MvcResult result = this.mockMvc.perform(get("/test/param/get?id={id}", id).accept(MediaType.APPLICATION_JSON)).andReturn();

    // 方式2:通过param()方法指定参数
    //MvcResult result = this.mockMvc.perform(get("/test/param/get").param("id", String.valueOf(id)).accept(MediaType.APPLICATION_JSON)).andReturn();

    // 方式3:通过queryParam()方法指定参数
    MvcResult result = this.mockMvc.perform(get("/test/param/get").queryParam("id", String.valueOf(id)).accept(MediaType.APPLICATION_JSON)).andReturn();
    Assertions.assertEquals("OK: " + id, result.getResponse().getContentAsString());
}

测试POST接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 传递表单参数
@Test
public void testSimplePost() throws Exception {
    int id = 10;

    // 调用param()方法传递参数
    MvcResult result = this.mockMvc.perform(post("/test/simple/post")
            .param("id", String.valueOf(id))
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .accept(MediaType.APPLICATION_JSON))
            .andReturn();
    Assertions.assertEquals("{\"id\":10}", result.getResponse().getContentAsString());
}

// 传递JSON参数
@Test
public void testSimplePostJson() throws Exception {
    // 调用content()方法传递json字符串参数
    Subject subject = new Subject();
    subject.setId(10);
    String content = JSON.toJSONString(subject);
    MvcResult result = this.mockMvc.perform(post("/test/simple/post/json")
            .content(content)
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON))
            .andReturn();
    Assertions.assertEquals("{\"id\":10}", result.getResponse().getContentAsString());
}

测试文件上传

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void testFileUploadSingle() throws Exception {
    File file = new File("C:\\Users\\xxx\\Downloads\\test.jpg");
    String fileName = FilenameUtils.getName(file.getName());
    byte[] bytes = FileUtils.readFileToByteArray(file);
    MockMultipartFile mockMultipartFile = new MockMultipartFile("file", fileName, MediaType.MULTIPART_FORM_DATA_VALUE, bytes);
    this.mockMvc.perform(multipart("/test/upload/single").file(mockMultipartFile))
                .andExpect(status().isOk())
                .andExpect(content().string("OK"))
                .andDo(print());
}

定义预期结果

断言响应结果时,有2种方式: 1.使用JUnit提供的Assert断言工具判断返回结果,这是一种非常普遍和常见的方式 2.在MockMvc框架中可以通过andExpect()方法定义一个或多个预期结果,当其中一个期望结果断言失败时,就不会断言其他期望值了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 使用Junit断言工具判断返回结果是否符合预期
@Test
public void testAssertResult() throws Exception {
    MvcResult result = this.mockMvc.perform(get("/test/simple/get").accept(MediaType.APPLICATION_JSON)).andDo(print()).andReturn();
    Assert.assertEquals("OK", result.getResponse().getContentAsString());
}

// 在MockMvc框架中定义预期结果
@Test
public void testExpectations() throws Exception {
    this.mockMvc.perform(get("/test/simple/get").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())        // 预期响应状态码为200
            .andExpect(content().string("OK")) // 预期返回值为字符串“OK”
            .andDo(print());
}

相比于使用Junit的断言工具判断返回结果,在MockMvc框架中直接定义预期结果进行断言检查更加简洁。

写在最后

使用Spring提供的测试框架MockMvc可以非常方便地实现对HTTP服务接口进行单元测试,不要把基础的功能验证工作都交给测试童鞋,应该通过单元测试来保证代码迭代的稳定性。

【参考】 https://blog.csdn.net/coolcoffee168/article/details/88638042 springboot 单元测试 (controller层) 方法 -- MockMvc

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
技巧:ZStack如何做Integration Test
笔者工作2年有余,刚开始实习的时候是不知道自动化测试这种神器的,在刚开始工作的时候往往苦于救火灭火再救火,搞的心力憔悴,一度怀疑猿生。实践自动化测试后感觉生产力慢慢的解放了,那个时候搞的还是偏单机应用,测试的Cover也是止步在单机应用上。在接触到了ZStack以后,由于其产品化的特性,对软件质量要求偏高,然作为一个典型的分布式系统,测试的覆盖率却是较高的。在这篇文章,笔者想谈谈对自动化测试的一些想法。
泊浮目
2024/01/09
1700
SpringMvc 之MockMvc帮我们解决了什么问题
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如启动速度慢,测试验证不方便,依赖网络环境等,导致测试无法进行,为了尽可能的对Controller进行快速测试,通过引入MockMVC进行解决。
louiezhou001
2020/04/07
1.3K0
SpringBoot基础之MockMvc单元测试
SpringBoot创建的Maven项目中,会默认添加spring-boot-starter-test依赖。在《5分钟快速上手SpringBoot》中编写的单元测试使用了MockMvc。本篇文章就围绕MockMvc在SpringBoot中的使用进行讲解。
程序新视界
2019/05/26
11.8K0
基于SpringBoot聊单元测试的分层
之前分享了关于质量内建的话题关于单元测试引起了大家的讨论,对于单元测试这件事情本身是比较熟悉的,但大家的反馈是比较难执行,矛盾在于很多测试做不了单元测试,或者让测试做性价比不是很高,这件事情推给开发之后又容易不了了之,其中一个很重要的点是,测试和开发没有同频对话的能力,各种细节难以敲定,落地的实际价值不容易度量,所以这篇文章我就基于常见的springboot框架,聊一聊单元测试分层的几种实践方式,从测试的视角给同学们一些知识面的拓展,也让大家熟悉下单元测试的常见玩法。
周辰晨
2022/09/20
8340
基于SpringBoot聊单元测试的分层
Spring Boot 实战|RESTful API 构建示例
权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同的人访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题。
南风
2020/03/02
2.7K0
springboot 单元测试
请先阅读SpringBoot 使用MockMvc进行Controller的测试,这篇文章已经讲的很清楚了。概括而言,做法如下:
平凡的学生族
2019/05/25
6450
Java程序员的日常—— POI与JDBC、Mockmvc与单元测试
周日没怎么休息好,周一一天都迷迷糊糊的,不过还算是干了不少的活。 总结一下,大致有以下几点内容: 1 使用poi以及mysql jdbc实现了一个复杂excel的导入 2 基于工程原有的代码,书写spring mvc的业务代码以及测试用例 使用POI以及jdbc POI是用于处理excel文件很常用的工具,如果你的excel是比较老的版本,记xls结尾的,那么只使用poi就行了。如果是xlsx结尾的,还需要引入xssf的jar包。 参考maven的pom.xml配置: <!-- https:/
用户1154259
2018/01/17
6850
Spring Boot实战:Restful API的构建
  上一篇文章讲解了通过Spring boot与JdbcTemplate、JPA和MyBatis的集成,实现对数据库的访问。今天主要给大家分享一下如何通过Spring boot向前端返回数据。   在现在的开发流程中,为了最大程度实现前后端的分离,通常后端接口只提供数据接口,由前端通过Ajax请求从后端获取数据并进行渲染再展示给用户。我们用的最多的方式就是后端会返回给前端一个JSON字符串,前端解析JSON字符串生成JavaScript的对象,然后再做处理。本文就来演示一下Spring boot如何实现这种
用户2140019
2018/05/18
1.4K0
MockMvc -你需要一个测试基类
用例虽然能执行成功,但是还存在着不少问题。最为严重的,就是代码冗余度太高。两次模拟的HTTP请求,虽然请求的方式和发送内容不同,但是整个请求的组装、发送和结果验证过程是基本一致的。因此,我们可以考虑重构上述用例,将公共部分提取到父类中供其余测试用例使用。
Criss@陈磊
2019/09/17
1.1K0
单元测试不止Junit,会MockMvc才是高手!
在前面的章节我们介绍过 Junit 的使用,也了解过 spring-test,今天我们来了解一个新玩意 -- mock 测试。这里仅仅做一个入门,对返回视图和返回 Json 数据的方法进行测试演示,不会把所有的方法都介绍到,具体文档详见链接:Mock Test,本章节主要讲解以下两部分内容:
java思维导图
2019/09/17
2.1K0
单元测试不止Junit,会MockMvc才是高手!
SpringBoot restful api的单元测试
1.添加Springboot测试注解 @RunWith(SpringRunner.class) @SpringBootTest public class UserControllerTest { } 2.伪造mvc环境 // 注入Spring 工厂 @Autowired private WebApplicationContext wac; //伪造mvc环境 private MockMvc mockMvc; @Before public void setup()
Meet相识
2018/09/12
7540
Spring Boot的测试框架(一)
Spring Boot提供了多种测试框架,包括单元测试、集成测试、端到端测试等。在本文中,我们将介绍Spring Boot的测试框架,并给出一些实际的示例。
堕落飞鸟
2023/04/06
9310
SpringMVC 单元测试
引入包: import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
前Thoughtworks-杨焱
2021/12/08
2190
Spring Security项目Spring MVC开发RESTful API(二)
查询请求 常用注解 @RestController 标明此Controller提供RestAPI @RequestMapping 映射http请求url到java方法 @RequestParam 映射请求参数到java方法到参数 @PageableDefault 指定分页参数默认值 编写一个简单的UserController类 @RestController @RequestMapping(value = "/user") public class UserController { @Req
楠楠
2019/03/20
8210
Spring Security项目Spring MVC开发RESTful API(二)
使用MockMVC进行Controller单元测试
由于MockMVC是Spring框架自带的测试组件,因此只要在项目中引入spring-boot-starter-test这个测试套件就可以使用Spring-test库中的MockMVC了。 例如Maven项目的pom.xml中添加如下的依赖
Antony
2020/12/03
5.7K0
【保姆级教程】Spring Boot 单元测试
\1. 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。在Java中单元测试的最小单元是类。
芋道源码
2021/01/25
31.7K0
【保姆级教程】Spring Boot 单元测试
【保姆级教程】SpringBoot单元测试,文末介绍Postman的基本使用
1. 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。在Java中单元测试的最小单元是类。
Java团长
2021/01/20
2.1K1
【保姆级教程】SpringBoot单元测试,文末介绍Postman的基本使用
springboot之单元测试
来源:http://www.51testing.com springboot在写完之后,肯定都需要进行单元测试,如下给出一些样例   工程层次结构如图   代码如下:   controller: pa
顾翔
2019/12/11
2940
springboot之单元测试
单元测试
简介 @RequestBody方式 Controller /** * 药品索引--通过doctorTeamHot * @param searchRequest * @return */ @RequestMapping(value = "/searchDrugSpu") public RpcResponse searchDrugSpu(@RequestBody DrugSearchRequest searchRequest) { Integer size = searchRequest.g
HLee
2020/12/31
7410
单元测试
Spring集成TestNG测试MVC Controller
  在项目中需要写单元测试,如何保证写的单元测试的质量是比较高的。有以下几个原则。
良辰美景TT
2018/12/07
1.1K0
相关推荐
技巧:ZStack如何做Integration Test
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验