009 spring mvc controller unit test
2017-06-09 21:12
501 查看
009 spring mvc controller unit test
视频发布在youtube上面了https://youtu.be/d-u95Q5JJjs
优酷上面的链接
http://v.youku.com/v_show/id_XMjgxNDY1Nzc4MA==.html?f=49760672
接着008的项目操作。
首先处理一下008中分页显示的时候,500000条记录,页号显示不全的问题。
我这里使用的是themes-default风格。在这里找到easyui.css,里面找到
pagination-num,修改width属性即可。原来是2,我改成了10,顺便了解了一下CSS Units。
em Relative to the font-size of the element (2em means 2 times the size of the current font)
这里有详细介绍
https://www.w3schools.com/cssref/css_units.asp
.pagination .pagination-num { border-width: 1px; border-style: solid; margin: 0 2px; padding: 2px; width: 10em; height: auto; }
刷新一下就可以看到变化了。注意如果没有变化清空一下浏览器缓存,在浏览器端检查一下,easyui.css源码是否是修改过后的。
自定义PageList数,非常的方便,设置对应的属性就可以了。
pageSize:12,pageList:[12,100,200,300]
<table id="dg" class="easyui-datagrid" title="用户列表" style="width: 100%; height: 400px;pagination-num{width:200px}" data-options="rownumbers:true,striped:true,fitColumns:true,singleSelect:true,autoRowHeight:true,pagination:true, pageSize:12,pageList:[12,100,200,300],url:'${pageContext.request.contextPath}/getUsers',method:'get',toolbar:'#toolbar'">
TestGetUser增加一个断言判断user是否为空
... assertTrue(user != null); assertTrue(user.getName().equals("user1"));
增加测试依赖包
<!-- controller test --> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path-assert</artifactId> <version>2.2.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.10.19</version> <scope>test</scope> </dependency>
JsonPath 用来写JSON数据的断言判断的。下面是网址
https://github.com/json-path/JsonPath
新建测试类TestUserController,这里使用实际的service来操作数据库获取数据。
这个用来控制测试函数的执行顺序,添加,更新,删除,执行完毕后,对数据没有影响。
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:springmvc.xml") @WebAppConfiguration @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestUserController { public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); @Autowired private WebApplicationContext wac; private MockMvc mockMvc; private static String lastNewId; @Before public void init() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void testReturnPage() throws Exception { mockMvc.perform(get("/users")).andExpect(status().isOk()).andExpect(view().name("users")).andDo(print()); } @Test public void testRealApiGetUsers() throws Exception { // .accept方法是设置客户端可识别的内容类型 // .contentType,设置请求头中的Content-Type字段,表示请求体的内容类型 mockMvc.perform(get("/getUsers").accept(MediaType.APPLICATION_JSON_UTF8) .contentType(MediaType.APPLICATION_JSON_UTF8).param("page", "1").param("rows", "10")).andDo(print()) .andExpect(status().isOk()).andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.total").exists()).andExpect(jsonPath("$.rows").isArray()) .andExpect(jsonPath("$.rows", hasSize(10))); } @Test public void test001RealApiAddUser() throws Exception { MvcResult ret = mockMvc .perform(post("/users").accept(MediaType.APPLICATION_JSON_UTF8) .contentType(MediaType.APPLICATION_JSON_UTF8).param("name", "user1").param("age", "23") .param("gender", "女").param("email", "user1@126.com").param("teacherId", "1") .param("createTime", "2017-06-08 13:59:12").param("loginTime", "2017-06-08 13:59:12")) .andDo(print()).andExpect(status().isOk()) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.retCode").value(0)).andExpect(jsonPath("$.newId").exists()).andReturn(); MockHttpServletResponse resp = ret.getResponse(); String strContent = resp.getContentAsString(); JSONObject jsonObject = JSONObject.parseObject(strContent); lastNewId = jsonObject.get("newId").toString(); } @Test public void test002RealApiUpdateUser() throws Exception { mockMvc.perform(put("/users/" + lastNewId).accept(MediaType.APPLICATION_JSON_UTF8) .contentType(MediaType.APPLICATION_JSON_UTF8).param("name", "user1").param("age", "33") .param("gender", "男").param("email", "user1@126.com").param("teacherId", "2") .param("createTime", "2017-06-08 13:59:12").param("loginTime", "2017-06-08 13:59:12")) .andDo(print()).andExpect(status().isOk()) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.retCode").value(0)).andExpect(jsonPath("$.status").value("更新成功")); } @Test public void test003RealApiDeleteUser() throws Exception { mockMvc.perform(delete("/users/" + lastNewId).accept(MediaType.APPLICATION_JSON_UTF8) .contentType(MediaType.APPLICATION_JSON_UTF8)).andDo(print()).andExpect(status().isOk()) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.retCode").value(0)).andExpect(jsonPath("$.status").value("删除成功")); } }
在UserController里面做了点修改,添加用户的时候返回了该条记录的主键。顺便把返回类型改成了JSONObject
@RequestMapping(value = "/users", method = RequestMethod.POST) @ResponseBody public JSONObject addUserProc(User user) { // 处理新id生成 // 处理teacher类对象 user.setTeacher(teacherService.getTeacherById(user.getTeacherId())); int iRet = userService.insertUser(user); long newId = user.getId(); JSONObject jsonObject = new JSONObject(); if (iRet == 0) { logger.info("addUsersProc: " + JSON.toJSON("新建失败:" + JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss"))); jsonObject.put("status", "新建失败"); jsonObject.put("retCode", -1); } else { logger.info("addUsersProc: " + JSON.toJSON("新建用户:" + JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss"))); jsonObject.put("status", "新建成功"); jsonObject.put("retCode", 0); jsonObject.put("newId", newId); } return jsonObject; }
需要手动引入两个包,不知道为什么不能自动引入。
MethodSorters的作用,这里需求是希望测试函数按照顺序执行,先添加一条记录,获取ID,然后再使用ID删除刚刚添加的记录。
import static org.hamcrest.Matchers.hasSize; import org.junit.runners.MethodSorters;
现在可以右键-Run As选择JUnit Test
Mock Service测试
新建一个TestUserControllerMockService测试类@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:springmvc.xml") @WebAppConfiguration @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestUserControllerMockService { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @InjectMocks private UserController userController; @Mock private IUserService userService; @Before public void init() { //support @Mock annotation MockitoAnnotations.initMocks(this); //解决Controller返回字符串和Mapping字符串相同时提示错误的问题 InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); FastJsonHttpMessageConverter fastjsonMsgConv = this.wac.getBean(com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter.class); StringHttpMessageConverter stringMsgConv = this.wac.getBean(StringHttpMessageConverter.class); mockMvc = MockMvcBuilders.standaloneSetup(userController) .setViewResolvers(viewResolver) .setMessageConverters(fastjsonMsgConv,stringMsgConv) .build(); } @Test public void testApiGetUsers() throws Exception { DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = null; try { date = df.parse("2017-06-08 13:59:12"); } catch (ParseException e) { e.printStackTrace(); } List<User> users = new ArrayList<User>(); for (int i = 0; i < 3; ++i) { User user = new User(); user.setId(1L + i); user.setName("user" + Integer.toString(i + 1)); user.setAge(23 + i); user.setGender("女"); user.setEmail("user1@126.com"); user.setTeacherId(1L); user.setCreateTime(date); user.setLoginTime(date); users.add(user); } when(userService.getCount()).thenReturn(3L); when(userService.getUsersPagenition(1, 3)).thenReturn(users); mockMvc.perform(get("/getUsers").accept(MediaType.APPLICATION_JSON_UTF8) .contentType(MediaType.APPLICATION_JSON_UTF8).param("page", "1").param("rows", "3")).andDo(print()) .andExpect(status().isOk()).andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.total").exists()).andExpect(jsonPath("$.rows").isArray()) .andExpect(jsonPath("$.rows", hasSize(3))) .andExpect(jsonPath("$.rows[0].name").value("user1")) .andExpect(jsonPath("$.rows[0].gender").value("女")) .andExpect(jsonPath("$.rows[0].age").value(23)) .andExpect(jsonPath("$.rows[1].name").value("user2")) .andExpect(jsonPath("$.rows[1].age").value(24)); //verify Interactions with any mock verify(userService, times(1)).getCount(); verify(userService, times(1)).getUsersPagenition(1, 3); verifyNoMoreInteractions(userService); } }
@Mock: 需要被Mock的对象
@InjectMocks: 需要将Mock对象注入的对象, 此处就是Controller
下面这个是
MockitoAnnotations.initMocks(this);
@Before
初始化Mock对象, 通过MockMvcBuilders.standaloneSetup模拟一个Mvc测试环境,注入controller, 通过build得到一个MockMvc, 后面就用MockMvc的一些API做测试。
这里面因为使用了fastJson发现之前的springmvc配置需要修改一下,才能通过。暂时先保证学习进度,后面有机会再深入了解一下fastJson的相关配置。
相关错误提示
No qualifying bean of type 'com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter' available
<!-- 对于mvc没有映射过的请求,交给容器默认handler来处理,例如:js,css等静态资源 --> <mvc:default-servlet-handler /> <!-- FastJson 转换注册 --> <bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8" index="0"></constructor-arg> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> <!--设置fastjson特性 --> <property name="features"> <array> <!--设置null值也要输出,fastjson默认是关闭的 --> <value>WriteMapNullValue</value> <!--设置使用文本方式输出日期,fastjson默认是long --> <value>WriteDateUseDateFormat</value> </array> </property> <property name="fastJsonConfig"> <bean class="com.alibaba.fastjson.support.config.FastJsonConfig"> <property name="features"> <list> <value>AllowArbitraryCommas</value> <value>AllowUnQuotedFieldNames</value> <value>DisableCircularReferenceDetect</value> </list> </property> <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss"></property> </bean> </property> </bean> <mvc:annotation-driven conversion-service="conversionService"> <mvc:message-converters register-defaults="true"> <ref bean="stringHttpMessageConverter" /> <ref bean="fastJsonHttpMessageConverter" /> </mvc:message-converters> </mvc:annotation-driven>
现在应该可以直接run这个测试了
相关文章推荐
- SpringMVC MultiActionController的使用-最简化教程
- asp.net mvc 1.0(5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test(非原创)
- ts2+Spring的UnitTest编写(使用StrutsTestCase的子类StrutsSpringTestCase)
- Spring下的业务层Unit Test修正版
- 如何让 Spring MVC Controller 的同一个 URL 请求,根据逻辑判断返回 JSON 或者 HTML 视图?
- Spring下的Unit Test Notes 2nd
- Spring下的Unit Test笔记
- Spring3 MVC ---注解基本配置及@controller和 @RequestMapping 常用解
- spring3.0 MVC 继承SimpleFormController不执行onSubmit方法解决办法。
- 如何让 Spring MVC Controller 的同一个 URL 请求,根据逻辑判断返回 JSON 或者 HTML 视图?
- The flow of MVC in Spring -- Part I -- Dispatcher and Controller
- Spring Web MVC 的HandlerMapping的使用之-------ControllerClassNameHandlerMapping
- Using MVC improve UI Unit Test
- Struts2+Spring的UnitTest编写(使用StrutsTestCase的子类StrutsSpringTestCase)
- Spring参考手册 mvc:view-controller
- asp.net mvc 1.0(5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test(非原创)
- 返璞归真asp.net mvc 1.0(5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test【转】
- spring mvc MultiActionController !!!
- Spring3参考手册 mvc:view-controller
- Spring MVC Controller