【高效编程】SpringMVC框架如何与Junit整合,看这个就够了

举报
码农飞哥 发表于 2021/05/28 22:44:54 2021/05/28
【摘要】 您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧!本文主要介绍在SpringMVC框架整合Junit框架进行单元测试。闲话少述,让我们直入主题。 文章目录 系统环境引入依赖编写单元测试基类代码说明 MockMvcRequestBuilders返回结果的content-type是application/json的请求的单元测试g...

您好,我是码农飞哥,感谢您阅读本文!如果此文对您有所帮助,请毫不犹豫的一键三连吧!本文主要介绍在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>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

如上,引入了4个依赖,其中:

  1. junit 是Junit单元测试的基础依赖,它提供了@RunWith和@Test等单元测试必备的注解。<scope>test</scope> 则指明了该依赖的作用范围是test阶段。
  2. 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; } }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

代码说明

  1. @RunWith(SpringJUnit4ClassRunner.class) 注解表明使用SpringJUnit4ClassRunner来运行测试用例。
  2. @WebAppConfiguration 注解表明使用的ApplicationContext将是WebApplicationContext类型的;value属性指定web应用的根;同时,他必须与 @ContextConfiguration一同使用。
  3. @ContextConfiguration注解的作用是导入我们需要的配置文件或者类,这里指定了SpringMVC的配置文件
  4. @ActiveProfiles 注解是指定单元测试连接的环境。
  5. @TransactionConfiguration 注解是用与管理spring事务的。
  6. MockHttpServletRequest 类为了模拟HttpServletRequest 对象,可以通过它来设置请求头,这在需要鉴权的接口测试中十分实用。
  7. MockMvc 实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快,不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
    getMockResultStr 方法是封装了公共的测试方法以及响应参数。 其中:
MvcResult mvcResult = this.mockMvc .perform(requestBuilder) .andExpect(status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • perform方法是执行一个RequestBuilder请求,调用Controller的业务处理逻辑。
  • andExpect 方法是添加执行完成后的断言,添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确,此处是验证状态是否是200
  • andDo 方法是添加一个结果处理器,比如再此处是andDo(MockMvcResultHandlers.print())输出整个响应结果信息,可以在调试的时候使用。
  • andReturn:方法是执行完成后返回相应的结果。

MockMvcRequestBuilders

  1. RequestBuilder是用来构建请求的。其提供了一个方法buildRequest(ServletContext servletContext) 用于构建MockHttpServletRequest; 其主要有两个子类MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(文件上传时使用),即用来mock客户端请求需要的所有数据。
  2. 主要API有MockHttpServletRequestBuilder.get(String urlTemplate, Object… urlVariables): 根据uri模板和uri变量值得到一个GET请求方式的RequestBuilder,如果在controller的方法中method选择的是RequestMethod.GET,那在controllerTest中对应就要使用MockMvcRequestBuilders.get。
  3. 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);

  
 
  • 1
  • 2
  • 3
  • 4

post请求测试

post请求的测试就是调用MockMvcRequestBuilders的post方法, 在该方法中传入接口地址。

 MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/blockly/copy") .param("id", "1211"); success(requestBuilder);

  
 
  • 1
  • 2
  • 3

文件上传测试

文件上传的测试就是调用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);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

发送一个json格式的数据到Controller层

String requestJson = JSONObject.toJSONString(folderInfo); MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("//v1/works/save").contentType(MediaType.APPLICATION_JSON).content(requestJson)
 
  • 1
  • 2

返回结果是视图请求的单元测试

那么,问题来了,如果一个接口的返回结果是视图,那么这个接口的单元测试该如何写呢?比如下面这个接口:

   @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"; }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这个接口返回的是一个视图,就是名称为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()); }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通过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(); }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

被测试的MallMailJob类也可以通过@Autowired 注解直接注入进Spring IOC容器中。拿到被测试类的实例之后就可以直接调用被测试的方法,是不是灰常的简单呀。
在这里插入图片描述

总结

本文详细介绍在SpringMVC任何使用Junit框架。首先介绍了如何引入依赖,接着介绍了编写一个测试基类,并且对其中涉及的各个注解做了一个详细说明。最后就是罗列了各种测试情况。

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/116380284

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。