测试示例
测试普通控制器
//测试普通控制器
mockMvc.perform(get("/user/{id}", 1)) //执行请求
.andExpect(model().attributeExists("user")) //验证存储模型数据
.andExpect(view().name("user/view")) //验证viewName
.andExpect(forwardedUrl("/WEB-INF/jsp/user/view.jsp"))//验证视图渲染时forward到的jsp
.andExpect(status().isOk())//验证状态码
.andDo(print()); //输出MvcResult到控制台
测试普通控制器,但是URL错误,即404
//找不到控制器,404测试
MvcResult result = mockMvc.perform(get("/user2/{id}", 1)) //执行请求
.andDo(print())
.andExpect(status().isNotFound()) //验证控制器不存在
.andReturn();
Assert.assertNull(result.getModelAndView()); //自定义断言
得到MvcResult自定义验证
MvcResult result = mockMvc.perform(get("/user/{id}", 1))//执行请求
.andReturn(); //返回MvcResult
Assert.assertNotNull(result.getModelAndView().getModel().get("user")); //自定义断言
验证请求参数绑定到模型数据及Flash属性
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")); //验证视图
验证请求参数验证失败出错
mockMvc.perform(post("/user").param("name", "admin")) //执行请求
.andExpect(model().hasErrors()) //验证模型有错误
.andExpect(model().attributeDoesNotExist("name")) //验证存在错误的属性
.andExpect(view().name("showCreateForm")); //验证视图
文件上传
//文件上传
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")); //验证视图
JSON请求/响应验证
测试时需要安装jackson Json和JsonPath依赖:
com.fasterxml.jackson.core
jackson-databind
${jackson2.version}
com.jayway.jsonpath
json-path
${jsonpath.version}
test
版本:0.9.0、2.2.3
String requestBody = "{\"id\":1, \"name\":\"zhang\"}";
mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_JSON).content(requestBody)
.accept(MediaType.APPLICATION_JSON)) //执行请求
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) //验证响应contentType
.andExpect(jsonPath("$.id").value(1)); //使用Json path验证JSON 请参考http://goessner.net/articles/JsonPath/
String errorBody = "{id:1, name:zhang}";
MvcResult result = mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_JSON).content(errorBody)
.accept(MediaType.APPLICATION_JSON)) //执行请求
.andExpect(status().isBadRequest()) //400错误请求
.andReturn();
Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//错误的请求内容体
XML请求/响应验证
测试时需要安装spring oxm和xstream依赖:
com.thoughtworks.xstream
xstream
${xsream.version}
test
org.springframework
spring-oxm
${spring.version}
test
版本:1.4.4
//XML请求/响应
String requestBody = "1zhang";
mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_XML).content(requestBody)
.accept(MediaType.APPLICATION_XML)) //执行请求
.andDo(print())
.andExpect(content().contentType(MediaType.APPLICATION_XML)) //验证响应contentType
.andExpect(xpath("/user/id/text()").string("1")); //使用XPath表达式验证XML 请参考http://www.w3school.com.cn/xpath/
String errorBody = "1zhang";
MvcResult result = mockMvc.perform(post("/user")
.contentType(MediaType.APPLICATION_XML).content(errorBody)
.accept(MediaType.APPLICATION_XML)) //执行请求
.andExpect(status().isBadRequest()) //400错误请求
.andReturn();
Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//错误的请求内容体
异常处理
//异常处理
MvcResult result = mockMvc.perform(get("/user/exception")) //执行请求
.andExpect(status().isInternalServerError()) //验证服务器内部错误
.andReturn();
Assert.assertTrue(IllegalArgumentException.class.isAssignableFrom(result.getResolvedException().getClass()));
静态资源
//静态资源
mockMvc.perform(get("/static/app.js")) //执行请求
.andExpect(status().isOk()) //验证状态码200
.andExpect(content().string(CoreMatchers.containsString("var")));//验证渲染后的视图内容包含var
mockMvc.perform(get("/static/app1.js")) //执行请求
.andExpect(status().isNotFound()); //验证状态码404
异步测试
//Callable
MvcResult result = mockMvc.perform(get("/user/async1?id=1&name=zhang")) //执行请求
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class))) //默认会等10秒超时
.andReturn();
mockMvc.perform(asyncDispatch(result))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id").value(1));
//DeferredResult
result = mockMvc.perform(get("/user/async2?id=1&name=zhang")) //执行请求
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class))) //默认会等10秒超时
.andReturn();
mockMvc.perform(asyncDispatch(result))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id").value(1));
此处请在第一次请求时加上 andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class)))这样会 等待结果返回/超时,无须自己设置线程等待了;此处注意request().asyncResult一定是在第一次请求发出;然后第二次通过 asyncDispatch进行异步请求。
添加自定义过滤器
mockMvc = webAppContextSetup(wac).addFilter(new MyFilter(), "/*").build();
mockMvc.perform(get("/user/1"))
.andExpect(request().attribute("filter", true));
全局配置
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"));
只要记住测试步骤,按照步骤操作,整个测试过程是非常容易理解的:
1、准备测试环境
2、通过MockMvc执行请求
3.1、添加验证断言
3.2、添加结果处理器
3.3、得到MvcResult进行自定义断言/进行下一步的异步请求
4、卸载测试环境