转自:https://www.cnblogs.com/xiaohunshi/p/5706943.html
概述
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等,这样会导致测试无法进行,为了可以对Controller进行测试,可以通过引入MockMVC进行解决。
简介
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
运行配置
用到的注解
- RunWith(SpringJUnit4ClassRunner.class): 表示使用Spring Test组件进行单元测试;
- WebAppConfiguration: 使用这个Annotate会在跑单元测试的时候真实的启一个web服务,然后开始调用Controller的Rest API,待单元测试跑完之后再将web服务停掉;
- ContextConfiguration: 指定Bean的配置文件信息,可以有多种方式,这个例子使用的是文件路径形式,如果有多个配置文件,可以将括号中的信息配置为一个字符串数组来表示;
基本框架
/**
* 演示MockMVC使用
* @author zhanyongzhi
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:**web-config.xml")
@WebAppConfiguration
public class MockMvcTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
测试逻辑
校验Controller处理之后,请求是否为成功状态,返回的内容是否包含了:"{'foo':'bar'}"字符串。
1 mockMvc调用perform,调用controller的业务处理逻辑
2 perform返回ResultActions,返回操作结果,通过ResultActions,提供了统一的验证方式。
3 使用StatusResultMatchers对请求结果进行验证
4 使用ContentResultMatchers对请求返回的内容进行验证
/**
* 演示MockMVC使用
* @author zhanyongzhi
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:**web-config.xml")
@WebAppConfiguration
public class MockMvcTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void demo() throws Exception {
mockMvc.perform(get("/demo/test").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"))
.andExpect(content().json("{'foo':'bar'}"));
}
}
另一个案例
先看一个测试例子1:
@Test public void createIncotermSuccess() throws Exception { IncotermTo createdIncoterm = new IncotermTo(); createdIncoterm.setId(new IncotermId(UUID.fromString("6305ff33-295e-11e5-ae37-54ee7534021a"))); createdIncoterm.setCode("EXW"); createdIncoterm.setDescription("code exw"); createdIncoterm.setLocationQualifier(LocationQualifier.DEPARTURE); when(inventoryService.create(any(IncotermTo.class))).thenReturn(createdIncoterm); mockMvc.perform(post("/secured/resources/incoterms/create").accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON) .content("{\"code\" : \"EXW\", \"description\" : \"code exw\", \"locationQualifier\" : \"DEPARTURE\"}".getBytes())) //.andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("id.value").exists()) .andExpect(jsonPath("id.value").value("6305ff33-295e-11e5-ae37-54ee7534021a")) .andExpect(jsonPath("code").value("EXW")); }
perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;
andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确;
andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台;
andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理;
看一个具体的例子2:
@Test public void testView() throws Exception { MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/user/1")) .andExpect(MockMvcResultMatchers.view().name("user/view")) .andExpect(MockMvcResultMatchers.model().attributeExists("user")) .andDo(MockMvcResultHandlers.print()) .andReturn(); Assert.assertNotNull(result.getModelAndView().getModel().get("user")); }
整个过程:
1、mockMvc.perform执行一个请求;
2、MockMvcRequestBuilders.get("/user/1")构造一个请求
3、ResultActions.andExpect添加执行完成后的断言
4、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
5、ResultActions.andReturn表示执行完成后返回相应的结果。
整个测试过程非常有规律:
1、准备测试环境
2、通过MockMvc执行请求
3.1、添加验证断言
3.2、添加结果处理器
3.3、得到MvcResult进行自定义断言/进行下一步的异步请求
4、卸载测试环境