SpringMVC框架整合Junit进行单元测试(案例详解)
作者:码农飞哥 发布时间:2022-04-10 20:53:37
本文主要介绍在SpringMVC框架整合Junit框架进行单元测试。闲话少述,让我们直入主题。
系统环境
软件 | 版本 |
---|---|
spring-webmvc | 4.3.6.RELEASE |
spring-test | 4.3.6.RELEASE |
junit | 4.12 |
引入依赖
<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>${spring.version}</version>
<scope>test</scope>
</dependency>
如上,引入了4个依赖,其中:
junit 是Junit单元测试的基础依赖,它提供了@RunWith和@Test等单元测试必备的注解。
<scope>test</scope>
则指明了该依赖的作用范围是test阶段。spring-test依赖可以理解成是spring框架与junit框架的桥梁。提供了
@WebAppConfiguration
等注解。
编写单元测试基类
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/test/java/spring-config.xml")
@ActiveProfiles("dev")
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public abstract class BaseControllerTest {
protected MockMvc mvc;
@Autowired
private WebApplicationContext context;
//获取系统上下文
protected WebApplicationContext getCtx() {
return this.context;
}
//初始化方法
@Before
public void setup() throws SQLException {
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
//封装返回结果
protected String getMockResultStr(MockHttpServletRequestBuilder requestBuilder) {
try {
MvcResult mvcResult = this.mockMvc
.perform(requestBuilder)
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
return response.getContentAsString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
代码说明
@RunWith(SpringJUnit4ClassRunner.class)
注解表明使用SpringJUnit4ClassRunner来运行测试用例。@WebAppConfiguration
注解表明使用的ApplicationContext将是WebApplicationContext类型的;value属性指定web应用的根;同时,他必须与@ContextConfiguration
一同使用。@ContextConfiguration
注解的作用是导入我们需要的配置文件或者类,这里指定了SpringMVC的配置文件@ActiveProfiles
注解是指定单元测试连接的环境。@TransactionConfiguration
注解是用与管理spring事务的。MockHttpServletRequest 类为了模拟HttpServletRequest 对象,可以通过它来设置请求头,这在需要鉴权的接口测试中十分实用。
MockMvc 实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快,不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
getMockResultStr 方法是封装了公共的测试方法以及响应参数。 其中:
MvcResult mvcResult = this.mockMvc
.perform(requestBuilder)
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
perform方法是执行一个RequestBuilder请求,调用Controller的业务处理逻辑。
andExpect 方法是添加执行完成后的断言,添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确,此处是验证状态是否是200
andDo 方法是添加一个结果处理器,比如再此处是
andDo(MockMvcResultHandlers.print())
输出整个响应结果信息,可以在调试的时候使用。andReturn:方法是执行完成后返回相应的结果。
MockMvcRequestBuilders
RequestBuilder是用来构建请求的。其提供了一个方法buildRequest(ServletContext servletContext) 用于构建MockHttpServletRequest; 其主要有两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(文件上传时使用),即用来mock客户端请求需要的所有数据。
主要API有MockHttpServletRequestBuilder.get(String urlTemplate, Object… urlVariables): 根据uri模板和uri变量值得到一个GET请求方式的RequestBuilder,如果在controller的方法中method选择的是RequestMethod.GET,那在controllerTest中对应就要使用MockMvcRequestBuilders.get。
MockHttpServletRequestBuilder.post(String urlTemplate, Object… urlVariables):同get类似,但是是post方法,通过param 方法来设置请求参数。
返回结果的content-type是application/json的请求的单元测试
get请求测试
get请求的测试就是调用MockMvcRequestBuilders的get方法, 在该方法中传入接口地址。
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/v1/works/lineup/set")
.param("id", "123")
.param("first_flag", String.valueOf(true));
String result = getMockResultStr(requestBuilder);
post请求测试
post请求的测试就是调用MockMvcRequestBuilders的post方法, 在该方法中传入接口地址。
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/blockly/copy")
.param("id", "1211");
success(requestBuilder);
文件上传测试
文件上传的测试就是调用MockMvcRequestBuilders的multipart方法, 在该方法中传入接口地址。
File file = new File(RestArmWorksControllerTest.class.getClassLoader().getResource("20201102172053.png").toURI());
MockMultipartFile mockMultipartFile = new MockMultipartFile("file", "20201102172053.png", "", new FileInputStream(file));
MockMultipartHttpServletRequestBuilder servletRequestBuilder = MockMvcRequestBuilders.multipart("/creation/fileUpload.do")
.file(mockMultipartFile);
String result = getMockResultStr(servletRequestBuilder);
发送一个json格式的数据到Controller层
String requestJson = JSONObject.toJSONString(folderInfo);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("//v1/works/save").contentType(MediaType.APPLICATION_JSON).content(requestJson);
返回结果是视图请求的单元测试
那么,问题来了,如果一个接口的返回结果是视图,那么这个接口的单元测试该如何写呢?比如下面这个接口:
@RequestMapping(value = "/edit")
public String edit(ModelMap model, HttpServletRequest request, HttpServletResponse response) {
Long scriptId = null;
if (StringUtils.isNotBlank(request.getParameter("scriptId"))) {
scriptId = Long.parseLong(request.getParameter("scriptId"));
}
if (scriptId != null) {
MallSuperscript mallSuperscript = superScriptService.getScriptById(scriptId);
model.addAttribute("superScript", mallSuperscript);
}
model.addAttribute("scriptTypeMap", ScriptType.toMap());
logger.info("角标编辑页面返回成功");
return "manage/superScript/edit";
}
这个接口返回的是一个视图,就是名称为edit.jsp页面。它的测试方法可以像下面这样写。
@Test
public void testEdit() throws Exception {
MvcResult mvcResult = mvc
.perform(
get("/manage/tab2/superScript/edit").sessionAttr("adminid", "1111")
.sessionAttr("platformid", 1001L).param("scriptId", "1111"))
.andExpect(status().isOk()).andDo(print()).andReturn();
assertEquals("manage/superScript/edit", mvcResult.getModelAndView().getViewName());
}
通过mvcResult.getModelAndView().getViewName()
获取视图的名称。
直接测试一个service的方法
上面的那些测试针对的都是Controller层的接口,那么如果要测试一个service层的方法,该如何处理呢?
public class MallMailJobTest extends BaseControllerTest {
private MallMailJob mallMailJob;
@Override
@Before
public void setup() throws SQLException {
super.setup();
mallMailJob = getCtx().getBean(MallMailJob.class);
}
/**
*
* @throws Exception
*/
@Test
public void testExecute() throws Exception {
mallMailJob.execute();
}
被测试的MallMailJob类也可以通过@Autowired
注解直接注入进Spring IOC容器中。拿到被测试类的实例之后就可以直接调用被测试的方法,是不是灰常的简单呀。
总结
本文详细介绍在SpringMVC任何使用Junit框架。首先介绍了如何引入依赖,接着介绍了编写一个测试基类,并且对其中涉及的各个注解做了一个详细说明。最后就是罗列了各种测试情况。
来源:https://blog.csdn.net/u014534808/article/details/116380284


猜你喜欢
- 一.前言这一篇来看看 SpringIOC 里面的一个细节点 , 来简单看看 BeanDefinition 这个对象 , 以及有没有办法对其进
- IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具,尤其在智
- 在Flutter开发过程中,我门有时候需要对一些数据进行本地的持久化存储,使用sp文件形式虽然也能解决问题,但是有时数据量较大的时候,显然我
- 1. String对象不可改变的特性下图显示了如下代码运行的过程:String s = "abcd"; s = s.co
- 调用和回调机制在一个应用系统中, 无论使用何种语言开发, 必然存在模块之间的调用, 调用的方式分为几种:1.同步调用同步调用是最基本并且最简
- 1. 为什么写这篇文章?事情是这样的,在 2021年6月10日早上我在CSDN上发布了文章《你真的懂Java怎么输出Hello World吗
- C#客户端程序,生成后是一个exe,如果带有大量的dll,那么dll和exe会混乱在一起,看起来非常混乱,我们可以建立一个文件夹,把dll放
- #region 监视文件夹的变化
- 本文提供了2段Android代码,实现了从Android客户端下载ZIP文件并且实现ZIP文件的解压功能,非常实用,有需要的Android开
- Java8已经发布很多年了,但是很多人在开发时仍然坚持使用着Date和SimpleDateFormat进行时间操作。SimpleDateFo
- 用户提出一个需求:当修改产品价格的时候,需要记录操作日志,什么时候做了什么事情。想必这个案例,只要是做过应用系统的小伙伴们,都应该遇到过吧?
- 一、程序的三种结构顺序结构分支结构循环结构二、条件语句if 语句是最有用的控制结构之一。 if … else …语句的语法:if (布尔表达
- 今天用NewtonSoft.JSon解析一个天气数据,数据格式如:{"status":1,"detail&qu
- FloatingActionButton项目在github上的主页:https://github.com/futuresimple/andr
- 二叉树(binary tree)是一颗树,其中每个节点都不能有多于两个的儿子。1.二叉树节点作为图的特殊形式,二叉树的基本组成单元是节点与边
- pom 文件依赖 <dependency> &
- 目录一、泛型类型二、为什么需要泛型三、类型擦除四、类型擦除的后遗症五、Kotlin 泛型六、上界约束七、类型通配符 & 星号投影八、
- 本人是从事互联网金融行业的,所以会接触到一些金融类的问题,常见的一种就是数字转汉字大小写的问题。所以抽空就写了一个小小的工具类,实现了数字转
- 异常与错误:异常:在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知
- Android 资源 id详解我们平时获取资源是通过 findViewById 方法进行的,比如我们常在onCreate方法中使用这样的语句