在有安全验证的情况下做单元测试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

2539-SpringSecurity系列--在有安全验证的情况下做单元测试Test的更多相关文章

  1. 关于JDBC技术中,调用MySQL中不建议在没有服务器身份验证的情况下建立SSL连接错误解决

    今天学习到了JBDC前沿:对JDBC编写步骤的封装,出现了一大串红色报错(当然,也不能叫报错,毕竟不是所有的红色都是错误eeror,) 错误如下: Establishing SSL connectio ...

  2. SpringSecurity系列之自定义登录验证成功与失败的结果处理

    一.需要自定义登录结果的场景 在我之前的文章中,做过登录验证流程的源码解析.其中比较重要的就是 当我们登录成功的时候,是由AuthenticationSuccessHandler进行登录结果处理,默认 ...

  3. AngularJs 入门系列-2 表单验证

    对于日常的开发来说,最常见的开发场景就是通过表单编辑数据,这里涉及的问题就是验证问题. angularjs 内置已经支持了常见的验证方式,可以轻松实现表单验证. 1. 绑定 为了方便,我们在 $sco ...

  4. 前端测试框架Jest系列教程 -- Expect(验证)

    写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多“Matchers”,这些“匹配器”允许您验证不同的东西. Expect 可以验证什么 Jest中 ...

  5. 【FICO系列】SAP FI验证故障排除(调试)

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[FICO系列]SAP FI验证故障排除(调试) ...

  6. 【SpringSecurity系列2】基于SpringSecurity实现前后端分离无状态Rest API的权限控制原理分析

    源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...

  7. Spring Boot干货系列:(十二)Spring Boot使用单元测试(转)

    前言这次来介绍下Spring Boot中对单元测试的整合使用,本篇会通过以下4点来介绍,基本满足日常需求 Service层单元测试 Controller层单元测试 新断言assertThat使用 单元 ...

  8. 用SignalR 2.0开发客服系统[系列4:负载均衡的情况下使用SignalR]

    前言 交流群:195866844 目录: 用SignalR 2.0开发客服系统[系列1:实现群发通讯] 用SignalR 2.0开发客服系统[系列2:实现聊天室] 用SignalR 2.0开发客服系统 ...

  9. [js高手之路]深入浅出webpack教程系列6-插件使用之html-webpack-plugin配置(下)

    上文我们对html-webpack-plugin的实例htmlWebpackPlugin进行了遍历分析,讲解了几个常用属性( inject, minify )以及自定义属性的添加,本文,我们继续深入他 ...

随机推荐

  1. OPRF

    在PSI中经常用到OPRF技术,现在系统学习一下. PRF Pseudo Random Function,伪随机函数,主要就是用来产生为伪随机数的. 伪随机数 什么伪随机数? 伪随机数是用确定性的算法 ...

  2. GitHub 毕业年鉴「GitHub 热点速览 v.22.20」

    GitHub 毕业需要什么呢?一个 PR!那么提交一个 PR 需要什么?也许你是使用终端命令来提交 git 操作的,那么你可以了解下 Bash-Oneliner,收录了大量好用的 bash 命令,虽然 ...

  3. windows 10 21H1 顶部任务栏点击音量或其他图标不出弹框

    右键任务栏,按照图片中描述操作

  4. [Java反序列化]jdk原生链分析

    jdk原生链分析 原文链接 作为jdk中目前发现的原生链,还是有必要要分析这个用法的.全文仅限尽可能还原挖掘思路 JDK7u21 在很多链中,TemplatesImpl一直发挥着不可或缺的作用,它是位 ...

  5. 深入解读SQL的聚集函数

    摘要:本文从基本聚集操作入手,介绍常用的SQL语法,以及一些扩展的聚集功能,同时会讲到在GaussDB(DWS)里聚集相关的一些优化思路. 本文分享自华为云社区<GaussDB(DWS) SQL ...

  6. python之装饰器补充与递归函数与二分查找

    目录 多层装饰器 有参装饰器 递归函数 基本演示 斐波那契数列 总结 小拓展 算法之二分法 简介 举例 总结 多层装饰器 我们已经知道了语法糖的作用是将装饰对象自动装饰到装饰器中,一个语法糖的应用我们 ...

  7. cpulimit-限制CPU速率

    CPULimit是一个简单的程序,它可以限制指定进程的CPU百分比. 1.安装依赖 root@localhost:~# apt-get -y install git 2.从GitHUB中克隆源码到本地 ...

  8. awk-文本处理【中文手册版】

    01. 简介 AWK是一个文本(面向行和列)处理工具,同时它也是一门脚本语言. AWK其名称得自于它的创始人 Alfred Aho .Peter Weinberger 和 Brian Kernigha ...

  9. pandas:聚合统计、数据分箱、分组可视化

    1.聚合统计 1.1描述统计 #df.describe(),对数据的总体特征进行描述 df.groupby('team').describe() df.groupby('team').describe ...

  10. linux挂载新硬盘并进行分区格式化

    最近要给小伙伴们写几篇文章,关于<linux下误删除文件之后该如何恢复>.对于没有进程占用的文件想要进行数据恢复,不同的文件系统格式需要使用不同的工具,比如:ext4.xfs等.我找遍了我 ...