MockMvc简单使用

1、概念

MockMvc是服务端 Spring MVC测试支持的主入口点。可以用来模拟客户端请求,用于测试。

2、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 [请求]对象


常用测试
MockMvcRequestBuilders.
1.测试普通测试器
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到控制台
2.得到MvcResult自定义验证
MvcResult result = mockMvc.perform(get("/user/{id}", 1))//执行请求  
        .andReturn(); //返回MvcResult  
Assert.assertNotNull(result.getModelAndView().getModel().get("user")); //自定义断言   

3.验证请求参数绑定到模型数据及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")); //验证视图  

4.文件上传
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")); //验证视图  

5.JSON请求/响应验证
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()));//错误的请求内容体
6.异步测试
 //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));  
7.全局配置
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"));  
  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 创建一个Spring Boot项目,并添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> ``` 2. 创建一个用户实体类和一个用户DAO接口,用于查询用户信息。 ```java public class User { private Long id; private String username; private String password; private List<String> roles; // getter and setter } public interface UserDAO { User findByUsername(String username); } ``` 3. 创建一个自定义的UserDetailsService,用于加载用户信息,并实现UserDetails接口。 ```java @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserDAO userDAO; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userDAO.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), AuthorityUtils.createAuthorityList(user.getRoles().toArray(new String[0])) ); } } ``` 4. 创建一个SecurityConfig类,用于配置Spring Security。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/") .invalidateHttpSession(true) .deleteCookies("JSESSIONID") .and() .csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } } ``` 5. 创建一个AdminController类,用于测试权限控制。 ```java @RestController @RequestMapping("/admin") public class AdminController { @GetMapping("/hello") public String hello() { return "Hello, Admin!"; } } ``` 6. 在application.properties中配置MyBatis和数据库信息。 ```properties mybatis.mapper-locations=classpath:mapper/*.xml spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` 7. 创建一个测试类,测试权限控制。 ```java @RunWith(SpringRunner.class) @SpringBootTest public class SecurityTest { @Autowired private WebApplicationContext context; private MockMvc mockMvc; @Before public void setUp() { mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build(); } @Test public void testAdmin() throws Exception { mockMvc.perform(get("/admin/hello") .with(user("admin").password("admin").roles("ADMIN"))) .andExpect(status().isOk()) .andExpect(content().string("Hello, Admin!")); } @Test public void testUser() throws Exception { mockMvc.perform(get("/admin/hello") .with(user("user").password("user").roles("USER"))) .andExpect(status().isForbidden()); } } ``` 运行测试类,可以看到测试通过,权限控制生效。 以上就是使用Spring Boot整合Spring Security和MyBatis实现权限管理的简单示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值