springmvc之测试MockMvc

一.前言

在项目完成之后,在对项目模块进行测试时,一般的流程是启动服务,在测试工具上进行测试,比如postMan,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等等问题,所以为了可以对Controller进行测试,我们引入了MockMVC。它实现了模拟web端对Http的请求,使得测试更加简洁方便、不依赖网络环境,而且提供了一套验证的工具。

二.测试流程

  1. MockMvcBuilder构造MockMvc的构造器MockMvcBuilder
  2. mockMvc调用perform,执行一个RequestBuilder请求,调用controller层的方法
  3. perform返回ResultActions,返回操作结果,通过ResultActions,提供了统一的验证方式
  4. 使用StatusResultMatchers对请求结果进行验证,如状态码
  5. 使用ContentResultMatchers对请求返回的内容进行验证
  6. 使用MockMvcResultHandlers对请求结果进行输出打印

三.MockMvc的API

(1)@RunWith注解

指定测试运行器,例如使用 SpringJUnit4ClassRunner.class

(2)@ContextConfiguration注解

执行要加载的配置文件,例如 classpath:application.xml 或 file:src/main/resources/DispatcherServlet-servlet.xml

(3)@WebAppConfiguration注解

用于声明测试时所加载的是WebApplicationContext【WebMVC的 XmlWebApplicationContext 是其实现类】
因为测试需要使用WebMVC对应的IOC容器对象

⑷ WebApplicationContext

WebMVC的IOC容器对象,需要声明并通过@Autowired自动装配进来

⑸ MockMvcRequestBuilders

用于构建MockHttpServletRequestBuilder
① get GET请求
② post POST请求
③ put PUT请求
④ delete DELETE请求
⑤ param(String name, String… values) 传递参数 K-V…

⑹ MockHttpServletRequestBuilder

用于构建 MockHttpServletRequest,它用于作为 MockMvc的请求对象

⑺ MockMvc

通过 MockMvcBuilders 的 webAppContextSetup(WebApplicationContext context) 方法 获取 DefaultMockMvcBuilder,再调用 build() 方法,初始化 MockMvc

① perform

perform(RequestBuilder requestBuilder) throws Exception

执行请求,需要传入 MockHttpServletRequest 对象【请求对象】

② andDo

andDo(ResultHandler handler) throws Exception

执行普通处理,例如 MockMvcResultHandlers的print() 方法用于 打印请求、响应及其他相关信息

③ andExpect

andExpect(ResultMatcher matcher) throws Exception
执行预期匹配,例如:

MockMvcResultMatchers.status().isOk() 预期响应成功

MockMvcResultMatchers.content().string(final String expectedContent) 指定预期的返回结果内容[字符串]

MockMvcResultMatchers.content().contentType(String contentType) 指定预期的返回结果的媒体类型

MockMvcResultMatchers.forwardedUrl(final String expectedUrl) 指定预期的请求的URL链接

MockMvcResultMathcers.redirectedUrl(final String expectedUrl) 指定预期的重定向的URL链接

注意:当有一项不满足时,则后续就不会进行。

④ andReturn

andReturn()
返回 MvcResult [请求访问结果]对象

⑤ getRequest

getRequest()
返回 MockHttpServletRequest [请求]对象

四.springboot项目测试

1.初始化
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BaseTestNg extends AbstractTestNGSpringContextTests {
    @Autowired
    private WebApplicationContext wac;

    public MockMvc mockMvc;

    @BeforeClass
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
}
2.get请求测试

controller层方法

	@GetMapping("/hello")
    public String hello(int a){
        System.out.println("hello =>");
        return "hello world:"+a;
    }

测试用例

    @Test(dataProvider = "num")
    public void testUser(int a) throws Exception {
        MvcResult result = mockMvc.perform(get("/hello")
        .param("a",a+""))
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        Assert.assertNotNull(result);
    }
    
   @DataProvider(name = "num")
    public Object[][] provideData() {
        return new Object[][] { { 1}, { 2}, { 4} };
    }

测试结果
springmvc之测试MockMvc
springmvc之测试MockMvc

3.post测试

controller层方法

   @PostMapping("/login")
    public String login(User user){
        System.out.println("用户:"+user.toString());
        return "结果:"+"用户名"+user.getUsername()+"  密码"+user.getPassword();
    }

测试用例

 @Test(dataProvider = "users")
    public void testLogin(User user) throws Exception {
        mockMvc.perform(post("/login")
                .contentType(MediaType.APPLICATION_FORM_URLENCODED)  //数据的格式
                .param("username", user.getUsername()).param("password", user.getPassword()))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
    }

    @DataProvider(name = "users")
    public Object[][] userList() {
        return new Object[][] { { new User("1","1")},
                { new User("2","2")},
                { new User("3","3")} };
    }

测试
springmvc之测试MockMvc
springmvc之测试MockMvc