准备:Maven依赖

 <!-- Spring和MVC的包这里不列出来了,webmvc,aspects,orm,其他maven会自动导 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version> 4.1.3.RELEASE</version>
<scope>provided</scope>
</dependency>

1、控制器例子

 package henu.controller;

 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import henu.entity.Exam; /**
* @ClassName: MockTestController <br/>
* @Describtion: Mock框架测试用例. <br/>
* @date: 2018年4月19日 下午2:02:47 <br/>
* @author Beats <br/>
* @version v1.0
*/
@Controller
public class MockTestController { @RequestMapping("/hello")
@ResponseBody
public String hello(String hello) {
return hello + " world!";
} @RequestMapping("/json")
@ResponseBody
public Exam json(String json) {
Exam e = new Exam();
e.setId(123);
e.setSubject(json);
return e;
}
  }

2、测试例子

 package henu.test;

 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.fileUpload;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import javax.annotation.Resource; import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext; /**
* @ClassName: TestMock <br/>
* @Describtion: 使用Spring集成的Mock框架测试web应用的控制器. <br/>
* @date: 2018年4月19日 下午1:58:22 <br/>
* @author Beats <br/>
* @version v1.0
*/
//这个必须使用junit4.9以上才有
@RunWith(SpringJUnit4ClassRunner.class)
//单元测试的时候真实的开启一个web服务,测试完毕就关闭
@WebAppConfiguration
//配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
@Transactional
@ContextConfiguration(locations={"classpath:spring.xml","classpath:springmvc.xml"})
//@ContextConfiguration(locations="classpath:spring*.xml")
public class TestMock { /**
* web应用的上下文
*/
@Resource
private WebApplicationContext context;
/**
* Mock框架的核心类
*/
private MockMvc mockMVC; @Before
public void initMockMVC() {
this.mockMVC = MockMvcBuilders.webAppContextSetup(context).build();
} @Test
public void testStringResult() throws Exception{ String res = mockMVC.perform(get("/hello")
.param("hello", "This is my")
.contentType(MediaType.TEXT_HTML)
.accept(MediaType.TEXT_HTML))
.andExpect(status().isOk())//期望值
.andDo(print())//打印结果
.andReturn().getResponse().getContentAsString();//结果字符串
System.err.println(res); } @Test
public void testJsonResult() throws Exception{ String res = mockMVC.perform(get("/json")
.param("json", "JAVA")
.param("hah", "hah")
//请求参数的类型
.contentType(MediaType.TEXT_HTML)
//希望服务器返回的值类型
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())//期望值
.andDo(print())//打印结果
.andReturn().getResponse().getContentAsString();//结果字符串
System.err.println(res);
} @Test
public void testModelResult() throws Exception{ String res = mockMVC.perform(get("/json")
.param("json", "JAVA")
.param("hah", "hah")
//请求参数的类型
.contentType(MediaType.TEXT_HTML)
//希望服务器返回的值类型
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())//期望值
.andDo(print())//打印结果
.andReturn().getResponse().getContentAsString();//结果字符串
System.err.println(res);
} @Test
public void testOthers() throws Exception {
byte[] bytes = new byte[] {1, 2};
mockMVC.perform(
fileUpload("/user/{id}/icon", 1L).file("icon", bytes)) //执行文件上传
.andExpect(model().attribute("icon", bytes)) //验证属性相等性
.andExpect(view().name("success")); //验证视图 // mockMvc.perform(post("/user").param("name", "zhang")) //执行传递参数的POST请求(也可以post("/user?name=zhang"))
// .andExpect(handler().handlerType(UserController.class)) //验证执行的控制器类型
// .andExpect(handler().methodName("create")) //验证执行的控制器方法名
// .andExpect(model().hasNoErrors()) //验证页面没有错误
// .andExpect(flash().attributeExists("success")) //验证存在flash属性
// .andExpect(view().name("redirect:/user")); //验证视图
}
}

函数解释:

     /**
* perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;
* get:声明发送一个get请求的方法。MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的。另外提供了其他的请求的方法,如:post、put、delete等。
* param:添加request的参数,如上面发送请求的时候带上了了pcode = root的参数。假如使用需要发送json数据格式的时将不能使用这种方式
* andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确(对返回的数据进行的判断);
* andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台(对返回的数据进行的判断);
* andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理(对返回的数据进行的判断)
*/
注意上面contentType需要设置成MediaType.APPLICATION_JSON,即声明是发送“application/json”格式的数据。使用content方法,将转换的json数据放到request的body中。

没有Mock框架怎么样?

  1.直接使用httpClient或者Okhttp 这方法各种麻烦
  2.使用Spring 提供的RestTemplate错误不好跟踪,必须开着服务器  

spring开发中,可以使用Spring自带的MockMvc这个类进行Mock测试

所谓的Mock测试,这里我举一个通俗易懂的例子,像servlet API中的HttpServletRequest对象是Tomcat容器生成的。我们无法手动的new出来,于是就有了所谓的Mock测试

运行配置

用到的注解:

  • RunWith(SpringJUnit4ClassRunner.class): 表示使用Spring Test组件进行单元测试;
  • WebAppConfiguration: 使用这个Annotate会在跑单元测试的时候真实的启动一个web服务,然后开始调用Controller的Rest API,待单元测试跑完之后再将web服务停掉;
  • ContextConfiguration: 指定Bean的配置文件信息,可以有多种方式,这个例子使用的是文件路径形式,如果有多个配置文件,可以将括号中的信息配置为一个字符串数组来表示;controller,component等都是使用注解,需要注解指定spring的配置文件,扫描相应的配置,将类初始化等。
  • TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用

为什么要进行事务回滚:

  • 测试过程对数据库的操作,会产生脏数据,影响我们数据的正确性
  • 不方便循环测试,即假如这次我们将一个记录删除了,下次就无法再进行这个Junit测试了,因为该记录已经删除,将会报错。
  • 如果不使用事务回滚,我们需要在代码中显式的对我们的增删改数据库操作进行恢复,将多很多和测试无关的代码

Mock全局配置

 mockMvc = webAppContextSetup(wac)
.defaultRequest(get("/user/1").requestAttr("default", true)) //默认请求 如果其是Mergeable类型的,会自动合并的哦mockMvc.perform中的RequestBuilder
.alwaysDo(print()) //默认每次执行请求后都做的动作
.alwaysExpect(request().attribute("default", true)) //默认每次执行后进行验证的断言
.build(); mockMvc.perform(get("/user/1"))
.andExpect(model().attributeExists("user"));

Spring+Junit+Mock测试web项目,即Controller的更多相关文章

  1. Spring Boot构建的Web项目如何在服务端校验表单输入

    本文首发于个人网站:Spring Boot构建的Web项目如何在服务端校验表单输入 这个例子用于演示在Spring Boot应用中如何验证Web 应用的输入,我们将会建立一个简单的Spring MVC ...

  2. Spring mvc创建的web项目,如何获知其web的项目名称,访问具体的链接地址?

    Spring mvc创建的web项目,如何获知其web的项目名称,访问具体的链接地址? 访问URL:  http://localhost:8090/firstapp/login 在eclipse集成的 ...

  3. 使用IDEA搭建一个 Spring + Spring MVC + Mybatis 的Web项目 ( 零配置文件 )

    前言: 除了mybatis 不是零配置,有些还是有xml的配置文件在里面的. 注解是Spring的一个构建的一个重要手段,减少写配置文件,下面解释一下一些要用到的注解: @Configuration  ...

  4. spring boot + Thymeleaf开发web项目

    "Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等.大多数情况下Web应用程序将使用 spring- ...

  5. spring学习(四) ———— 整合web项目(SSH)

    清楚了spring的IOC 和 AOP,最后一篇就来整合SSH框架把,记录下来,以后应该会用的到. --WH 一.web项目中如何使用spring? 当tomcat启动时,就应该加载spring的配置 ...

  6. spring(四) 手动整合web项目(SSH)

    清楚了spring的IOC 和 AOP,最后一篇就来整合SSH框架把,记录下来,以后应该会用的到. --WH 一.web项目中如何使用spring? 当tomcat启动时,就应该加载spring的配置 ...

  7. spring boot之创建web项目并访问jsp页面

    1,创建spring boot的web项目 刚创建好的项目路径如下: 2,pom中要有下面的依赖 <dependency> <groupId>org.springframewo ...

  8. Spring Boot快速开发Web项目

    我们以前使用Spring框架的时候,需要首先在pom文件中增加对相关的的依赖,然后新建Spring相关的xml文件,而且往往那些xml文件还不会少.然后继续使用tomcat或者jetty作为容器来运行 ...

  9. IDEA创建一个Spring MVC 框架Java Web项目,Gradle构建

    注:此篇有些细节没写出,此文主要写重要的环节和需要注意的地方,轻喷 新建项目 选择Gradle , 勾选java 和 web.之后就是设定项目路径和名称,这里就不啰嗦了. build.gradle文件 ...

随机推荐

  1. 关于 vs 2012 键盘无法输入的问题

    使用vs2012 新建了一个类文件之后,vs2012的编辑界面突然出现奇怪的问题,键盘无法输入! 最后调查的结果是由于resharper插件导致的. 可以将插件禁用然后启用. 也可以删除resharp ...

  2. 最近一直是web前段,没什么意思,所以就不发资料了

    最近一直是web前段,没什么意思,所以就不发资料了 版权声明:本文为博主原创文章,未经博主允许不得转载.

  3. [51nod1106]质数检测

    解题关键: 根据质数的定义,在判断一个数n是否是质数时,我们只要用1至n-1去除n,看看能否整除即可.但我们有更好的办法.先找一个数m,使m的平方大于n,再用<=m的质数去除n(n即为被除数), ...

  4. UGUI解决嵌套使用多个ScrollRect时的Drag拖动冲突问题

    很简单,直接看代码: using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine; /// <summary& ...

  5. nodejs处理页面跳转url地址的处理

    使用status函数设置状态码 router.get("/list/:id",(req,res)=>{ let id = req.params.id; res.locals. ...

  6. R: 时间处理(R自带函数)

    ################################################### 问题:时间处理    18.4.28 如何用,as.Date()规范日期.计算日期的加减等?? ...

  7. Linux系统挂载FAT32的U盘

    1:将U盘插入USB接口,检查是否插好 2:用fdisk命令检查分区和USB设备信息 [root@yhwang ~]# fdisk -l Disk /dev/sda: 1000.2 GB, 10002 ...

  8. Error creating form bean of class com.onlinebookstore.presentation.CatalogBean

    Error creating form bean of class com.onlinebookstore.presentation.CatalogBean 可能是action form未编译 这个问 ...

  9. Tensorflow函数——tf.placeholder()函数

    tf.placeholder()函数 Tensorflow中的palceholder,中文翻译为占位符,什么意思呢? 在Tensoflow2.0以前,还是静态图的设计思想,整个设计理念是计算流图,在编 ...

  10. Ajax.BeginForm 使用过程中遇到的问题

    一.Ajax.BeginForm设置的路由在浏览器中解析不到. 问题截图:在视图中设置"Counter/Index",在浏览器中显示的是"action='/'" ...