恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Spring Boot中编写单元测试

  • 首页
  • 资讯中心
  • /
  • Spring Boot中编写单元测试

相关资讯

YOLO 小目标涨点|2504 张输电线路销钉绝缘子 4 类 VOC/YOLO 数据集,无人机电力缺陷检测落地全流程 2026/8/26 19:02:27
NVIDIA ACE-RTL 论文精读:RTL 专用模型进入 Agent 闭环,为什么能把 Spec-to-RTL APR 推到 96.15%? 2026/8/26 18:57:26
用 AI 写周报,我把时间从 2 小时压到 10 分钟 2026/8/26 18:57:26

最新资讯

GPUIX元素完全参考:11个原生元素一次看懂(附代码示例)
Spring AI 2.0正式GA、LangChain4j 1.19发布:Java程序员做AI,为什么不用转Python?
深耕劳务行业五年,我观察到的湖南劳务外包市场真实现状
离散傅里叶变换DFT代码解析
文件和IO(2)
LX Music 桌面版:免费开源的多源音乐聚合播放器,三分钟跑起来

今日推荐

Python random 模块常用函数详解:从入门到实战
Hermes接入团队协作后,我推翻了三个效率假设
免费AI大模型调教指南:打造专属网文写作助手

本周热门

Nextcloud 桌面客户端:把同步交给它,你只管改文件
如何将 HTML 转成 Word 文档且格式不丢失?html-to-docx 使用教程
Anki 批量操作卡片完整指南:一次搞定上千张,不再逐张修改

本月精选

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

Spring Boot中编写单元测试

发布时间:2026/8/26 19:02:27
Spring Boot中编写单元测试 一、前言编写单元测试可以帮助开发人员编写高质量的代码提升代码质量减少Bug便于重构。Spring Boot提供了一些实用程序和注解用来帮助我们测试应用程序在Spring Boot中开启单元测试只需引入spring-boot-starter-test即可其包含了一些主流的测试库。本文主要介绍基于 Service和Controller的单元测试。二、引入spring-boot-starter-test在spring项目创建时默认是引入了spring-boot-starter-test但实际进行单元测试时是需要引入junit。引入具体如下dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdscopetest/scope/dependency或者直接引入dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency三、知识准备3.1 Unit4注解JUnit4中包含了几个比较重要的注解BeforeClass、AfterClass、Before、After和Test。其中 BeforeClass和AfterClass在每个类加载的开始和结束时运行必须为静态方法而Before和After则在每个测试方法开始之前和结束之后运行。见如下例子importorg.junit.*;importorg.junit.runner.RunWith;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;RunWith(SpringRunner.class)SpringBootTestpublicclassTestApplicationTests{BeforeClasspublicstaticvoidbeforeClassTest(){System.out.println(before class test);}BeforepublicvoidbeforeTest(){System.out.println(before test);}TestpublicvoidTest1(){System.out.println(test 112);Assert.assertEquals(2,11);}TestpublicvoidTest2(){System.out.println(test 224);Assert.assertEquals(4,22);}AfterpublicvoidafterTest(){System.out.println(after test);}AfterClasspublicstaticvoidafterClassTest(){System.out.println(after class test);}}运行输出如下... before class test before test test 112 after test before test test 224 after test after class test ...从上面的输出可以看出各个注解的运行时机。注意引入头信息必须按照上面的进行加载否则会造成After等不能生效。3.2 Assert上面代码中我们使用了Assert类提供的assert口方法下面列出了一些常用的assert方法assertEquals(“message”,A,B)判断A对象和B对象是否相等这个判断在比较两个对象时调用了equals()方法。assertSame(“message”,A,B)判断A对象与B对象是否相同使用的是操作符。assertTrue(“message”,A)判断A条件是否为真。assertFalse(“message”,A)判断A条件是否不为真。assertNotNull(“message”,A)判断A对象是否不为null。assertArrayEquals(“message”,A,B)判断A数组与B数组是否相等。3.3 MockMvc下文中对Controller的测试需要用到MockMvc技术。MockMvc从字面上来看指的是模拟的MVC即其可以模拟一个MVC环境向Controller发送请求然后得到响应。在单元测试中使用MockMvc前需要进行初始化如下所示privateMockMvcmockMvc;AutowiredprivateWebApplicationContextwac;BeforepublicvoidsetupMockMvc(){mockMvcMockMvcBuilders.webAppContextSetup(wac).build();}MockMvc模拟MVC请求模拟一个get请求mockMvc.perform(MockMvcRequestBuilders.get(/hello?name{name},wno704));模拟一个post请求mockMvc.perform(MockMvcRequestBuilders.post(/user/{id},1));模拟文件上传mockMvc.perform(MockMvcRequestBuilders.fileUpload(/fileupload).file(file,文件内容.getBytes(utf-8)));模拟请求参数// 模拟发送一个message参数值为hellomockMvc.perform(MockMvcRequestBuilders.get(/hello).param(message,hello));// 模拟提交一个checkbox值name为hobby值为sleep和eatmockMvc.perform(MockMvcRequestBuilders.get(/saveHobby).param(hobby,sleep,eat));也可以直接使用MultiValueMap构建参数MultiValueMapString,StringparamsnewLinkedMultiValueMapString,String();params.add(name,wno704);params.add(hobby,sleep);params.add(hobby,eat);mockMvc.perform(MockMvcRequestBuilders.get(/hobby/save).params(params));模拟发送JSON参数StringjsonStr{\username\:\Dopa\,\passwd\:\ac3af72d9f95161a502fd326865c2f15\,\status\:\1\};mockMvc.perform(MockMvcRequestBuilders.post(/user/save).content(jsonStr.getBytes()));实际测试中要手动编写这么长的JSON格式字符串很繁琐也很容易出错可以借助Spring Boot自带的Jackson技术来序列化一个Java对象可参考Spring Boot中的JSON技术如下所示UserusernewUser();user.setUsername(Dopa);user.setPasswd(ac3af72d9f95161a502fd326865c2f15);user.setStatus(1);StringuserJsonmapper.writeValueAsString(user);mockMvc.perform(MockMvcRequestBuilders.post(/user/save).content(userJson.getBytes()));其中mapper为com.fasterxml.jackson.databind.ObjectMapper对象。模拟Session和CookiemockMvc.perform(MockMvcRequestBuilders.get(/index).sessionAttr(name,value));mockMvc.perform(MockMvcRequestBuilders.get(/index).cookie(newCookie(name,value)));设置请求的Content-TypemockMvc.perform(MockMvcRequestBuilders.get(/index).contentType(MediaType.APPLICATION_JSON_UTF8));设置返回格式为JSONmockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1).accept(MediaType.APPLICATION_JSON));模拟HTTP请求头mockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1).header(name,values));MockMvc处理返回结果期望成功调用即HTTP Status为200mockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1)).andExpect(MockMvcResultMatchers.status().isOk());期望返回内容是application/jsonmockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1)).andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON));检查返回JSON数据中某个值的内容mockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1)).andExpect(MockMvcResultMatchers.jsonPath($.username).value(wno704));这里使用到了jsonPath$代表了JSON的根节点。更多关于jsonPath的介绍可参考 https://github.com/json-path/JsonPath。判断Controller方法是否返回某视图mockMvc.perform(MockMvcRequestBuilders.post(/index)).andExpect(MockMvcResultMatchers.view().name(index.html));比较ModelmockMvc.perform(MockMvcRequestBuilders.get(/user/{id},1)).andExpect(MockMvcResultMatchers.model().size(1)).andExpect(MockMvcResultMatchers.model().attributeExists(password)).andExpect(MockMvcResultMatchers.model().attribute(username,wno704));比较forward或者redirectmockMvc.perform(MockMvcRequestBuilders.get(/index)).andExpect(MockMvcResultMatchers.forwardedUrl(index.html));// 或者mockMvc.perform(MockMvcRequestBuilders.get(/index)).andExpect(MockMvcResultMatchers.redirectedUrl(index.html));比较返回内容使用content()// 返回内容为hellomockMvc.perform(MockMvcRequestBuilders.get(/index)).andExpect(MockMvcResultMatchers.content().string(hello));// 返回内容是XML并且与xmlCotent一样mockMvc.perform(MockMvcRequestBuilders.get(/index)).andExpect(MockMvcResultMatchers.content().xml(xmlContent));// 返回内容是JSON 并且与jsonContent一样mockMvc.perform(MockMvcRequestBuilders.get(/index)).andExpect(MockMvcResultMatchers.content().json(jsonContent));输出响应结果mockMvc.perform(MockMvcRequestBuilders.get(/index)).andDo(MockMvcResultHandlers.print());四、测试Service具体如下RunWith(SpringRunner.class)SpringBootTestpublicclassUserServiceTest{AutowiredUserServiceuserService;Testpublicvoidtest(){Useruserthis.userService.findByName(scott);Assert.assertEquals(用户名为scott,scott,user.getUsername());}}运行后JUnit没有报错说明测试通过即UserService的findByName方法可行。此外和在Controller中引用Service相比在测试单元中对Service测试完毕后数据能自动回滚只需要在测试方法上加上Transactional注解比如:TestTransactionalpublicvoidtest(){UserusernewUser();user.setId(this.userService.getSequence(seq_user));user.setUsername(JUnit);user.setPasswd(123456);user.setStatus(1);user.setCreateTime(newDate());this.userService.save(user);}运行测试通过查看数据库发现数据并没有被插入这样很好的避免了不必要的数据污染。五、测试Controller现有如下ControllerRestControllerpublicclassUserController{AutowiredUserServiceuserService;GetMapping(user/{userName})publicUsergetUserByName(PathVariable(valueuserName)StringuserName){returnthis.userService.findByName(userName);}PostMapping(user/save)publicvoidsaveUser(RequestBodyUseruser){this.userService.saveUser(user);}}现在编写一个针对于该ControllergetUserByName(PathVariable(value “userName”) String userName)方法的测试类RunWith(SpringRunner.class)SpringBootTestpublicclassUserControllerTest{privateMockMvcmockMvc;AutowiredprivateWebApplicationContextwac;BeforepublicvoidsetupMockMvc(){mockMvcMockMvcBuilders.webAppContextSetup(wac).build();}Testpublicvoidtest()throwsException{mockMvc.perform(MockMvcRequestBuilders.get(/user/{userName},scott).contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.jsonPath($.username).value(scott)).andDo(MockMvcResultHandlers.print());}}运行后JUnit通过控制台输出过程如下所示MockHttpServletRequest: HTTP Method GET Request URI /user/scott Parameters {} Headers {Content-Type[application/json;charsetUTF-8]} Handler: Type demo.springboot.test.controller.UserController Method public demo.springboot.test.domain.User demo.springboot.test.controller.UserController.getUserByName(java.lang.String) Async: Async started false Async result null Resolved Exception: Type null ModelAndView: View name null View null Model null FlashMap: Attributes null MockHttpServletResponse: Status 200 Error message null Headers {Content-Type[application/json;charsetUTF-8]} Content type application/json;charsetUTF-8 Body {id:23,username:scott,passwd:ac3af72d9f95161a502fd326865c2f15,createTime:1514535399000,status:1} Forwarded URL null Redirected URL null Cookies []继续编写一个针对于该ControllersaveUser(RequestBody User user)方法的测试类RunWith(SpringRunner.class)SpringBootTestpublicclassUserControllerTest{privateMockMvcmockMvc;AutowiredprivateWebApplicationContextwac;AutowiredObjectMappermapper;BeforepublicvoidsetupMockMvc(){mockMvcMockMvcBuilders.webAppContextSetup(wac).build();}TestTransactionalpublicvoidtest()throwsException{UserusernewUser();user.setUsername(Dopa);user.setPasswd(ac3af72d9f95161a502fd326865c2f15);user.setStatus(1);StringuserJsonmapper.writeValueAsString(user);mockMvc.perform(MockMvcRequestBuilders.post(/user/save).contentType(MediaType.APPLICATION_JSON_UTF8).content(userJson.getBytes())).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}}运行过程如下所示MockHttpServletRequest: HTTP Method POST Request URI /user/save Parameters {} Headers {Content-Type[application/json;charsetUTF-8]} Handler: Type demo.springboot.test.controller.UserController Method public void demo.springboot.test.controller.UserController.saveUser(demo.springboot.test.domain.User) Async: Async started false Async result null Resolved Exception: Type null ModelAndView: View name null View null Model null FlashMap: Attributes null MockHttpServletResponse: Status 200 Error message null Headers {} Content type null Body Forwarded URL null Redirected URL null Cookies []值得注意的是在一个完整的系统中编写测试单元时可能需要模拟一个登录用户信息SessionMockMvc也提供了解决方案可在初始化的时候模拟一个HttpSessionprivateMockMvcmockMvc;privateMockHttpSessionsession;AutowiredprivateWebApplicationContextwac;BeforepublicvoidsetupMockMvc(){mockMvcMockMvcBuilders.webAppContextSetup(wac).build();sessionnewMockHttpSession();UserusernewUser();user.setUsername(Dopa);user.setPasswd(ac3af72d9f95161a502fd326865c2f15);session.setAttribute(user,user);}

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号