zoukankan      html  css  js  c++  java
  • 2539-SpringSecurity系列--在有安全验证的情况下做单元测试Test

    在有安全验证的情况下做单元测试Test

    版本信息

    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.14.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <version>1.5.14.RELEASE</version>
        <!--实际里面spring-security-web的版本是4.2.7-->
    </dependency>
    
    
    
    
    

    添加依赖

    <!--spring-security单元测试-->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <version>4.2.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!--spring-security单元测试-->
    

    需求

    1. 在写单元测试时,需要模拟某个用户的登录状态
    2. 在写单元测试时,需要模拟某个用户具有某个权限,但又不想改变数据库
    3. 编写单元测试时,需求完整调用某个用户的登录

    解决需求:

    springSecurity提供了相关的组件spring-security-test,可参考官方文档(https://docs.spring.io/spring-security/site/docs/5.0.6.RELEASE/reference/htmlsingle/#test-method-withmockuser),该组件提供了相关的注解来来模拟用户登录信息或者调用用户登录的方法

    • @WithMockUser 模拟用户,手动指定用户名和授权
    • @WithAnonymousUser 模拟匿名用户
    • @WithUserDetails 模拟用户,给定用户名,通过自定义UserDetails来认证
    • @WithSecurityContext 通过SecurityContext构造器模拟用户

    例如

    @Test
    @WithMockUser(username="admin",roles={"USER","ADMIN"})
    public void getMessageWithMockUserCustomUser() {
    	String message = messageService.getMessage();
    	...
    }
    
    

    模拟了一个名叫admin的用户,拥有角色"USER","ADMIN"

    代码范例

    
    import com.alibaba.fastjson.JSONObject;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.security.test.context.support.WithUserDetails;
    import org.springframework.test.annotation.Rollback;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.MvcResult;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.context.WebApplicationContext;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
    import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.logout;
    import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
    import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
    import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    
    /**
     * 接口测试+ SpringSecurity的用户登录模拟
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Transactional
    @Rollback(true)// 事务自动回滚,默认是true。可以不写
    public class ExampleRestClientTest {
    
    
        private MockMvc mockMvc; // 模拟MVC对象,通过MockMvcBuilders.webAppContextSetup(this.wac).build()初始化。
    
        @Autowired
        private WebApplicationContext wac; // 注入WebApplicationContext
    
        @Before // 在测试开始前初始化工作
        public void setup() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).apply(springSecurity()).build();
        }
    
        @Test
        @WithUserDetails(value = "admin", userDetailsServiceBeanName = "customUserDetailsService")
        public void testQ1() throws Exception {
            Map<String, Object> map = new HashMap<>();
            map.put("param1", "valueaa");
    
            MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/secmenu/getUserMenuList")
                    .contentType(MediaType.APPLICATION_JSON_UTF8).content(JSONObject.toJSONString(map)))
                    .andExpect(status().is(200))// 模拟向testRest发送get请求
                    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))// 预期返回值的媒体类型text/plain;charset=UTF-8
                    .andReturn();// 返回执行请求的结果
    
        }
    
        @Test
        public void testFormLoginSuccess() throws Exception {
    
            // 测试登录成功
            mockMvc
                    .perform(formLogin("/login").user("admin").password("123456"))
                    .andExpect(authenticated());
        }
    
        @Test
        public void testFormLoginFail() throws Exception {
            // 测试登录失败
            mockMvc
                    .perform(formLogin("/login").user("admin").password("invalid"))
                    .andExpect(unauthenticated());
        }
    
        @Test
        public void testLogoutFail() throws Exception {
            // 测试退出登录
            mockMvc.perform(logout("/logout")).andExpect(unauthenticated());
        }
    }
    

    完整项目工程参考

    https://github.com/starmoon1994/springsecurity-collection

  • 相关阅读:
    操作系统演进和未来趋势(附下载)
    用树莓派构建一台服务器,永久运行网站
    用 Docker 构建 MySQL 主从环境
    (一)多线程:线程概述
    网站可访问性的五个自动化测试工具
    个人对前端工程化的理解
    MongoDB安装过程中出现service MongoDB failed to start,verify that you have sufficient privileges to start
    前端开发IDE
    atom插件:js,nodejs,es6补全,高度定制化
    atom离线手动安装atom插件
  • 原文地址:https://www.cnblogs.com/starmoon1994/p/9362333.html
Copyright © 2011-2022 走看看