sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.

时间:2022-09-29 03:28:20

遇到mock 测试简直就是神器,特别是要做代码覆盖率,直接测试controller就好了,缺点,虽然可以回滚事务,但是依赖数据库数据,解决,根据SpringBoot ,再建立一个专门跑单元测试的数据库,以及application.yml

想起以前用的 unitils 整合测试,巨额时间成本,都是在写XML.遇到时间变化的条件,还一点办法都没有,唯一觉得是优势的就是与环境解耦,不依赖数据库

sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.

sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.

sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.

pom配置

 <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!--<configuration>-->
<!--<skip>true</skip>-->
<!--</configuration>-->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<!--<skip>true</skip>-->
<source>1.8</source>
<target>1.8</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<includes>com.*</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

jenkins 集成了 sonar 配置 Analysis properties 一定要配置  sonar.tests=src/test/java 否则会吧单元测试的覆盖率也算上,坑爹,默认就应该排除掉

sonar.exclusions 可以排除掉,自相矛盾的规则(永远达不成,例如 全是静态方法的类,可以写成final 并且添加私有构造方法,这个私有构造方法,永远都覆盖不了,除非你还去反射调用),或者测试不会执行的类,这里我排除了SpringBoot的启动类

sonar.projectKey=testKey
sonar.projectName=testProject
sonar.projectVersion=1.0
sonar.sources=src/main/java
sonar.tests=src/test/java
sonar.exclusions=src/main/java/com/test/Application.java
sonar.java.binaries=target/classes
sonar.language=java
sonar.sourceEncoding=UTF-8

回滚事务

在测试类加上注解@Rollback

注意:之前喜欢在Controller 使用 @Transactional(propagation = Propagation.REQUIRES_NEW),但是这样的话,是强行开启一个新事务,不会加入上层事务,所以哪怕是Controller 也应该使用@Transactional(propagation = Propagation.REQUIRED)

否则@Rollback无效

如果是微服务SpringCloud,回滚不了另一个服务的事务,那么直接进入FallBack服务降级就好了

以下是我的测试类的注解部分

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Rollback
@Transactional
@ActiveProfiles(profiles = "dev")
public class BaseTests { }

加入SpringSecurity过滤器链

模拟用户登录,注意登录用户的权限问题

   @Autowired
protected TestRestTemplate restTemplate; @Autowired
protected WebApplicationContext wac; @Autowired
private Filter springSecurityFilterChain; @Autowired
private Filter invoiceContextFilter; protected MockMvc mockMvc; protected MockHttpSession session; @PostConstruct
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.addFilters(springSecurityFilterChain, invoiceContextFilter)
.build();
this.session = new MockHttpSession();
login();
getLoginSession("testuser", "789456a");
}
protected void login() throws Exception {
MvcResult result = this.mockMvc
.perform(get("/login"))
.andReturn();
Assert.assertNotNull(result.getModelAndView());
}
/**
* 获取登入信息session
*
* @return
* @throws Exception
*/
protected void getLoginSession(String name, String pwd) throws Exception { MvcResult result = this.mockMvc
.perform(post("/doLogin").contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("username", name).param("password",pwd)
.param("verifiCode", "ABCD"))
.andExpect(status().isFound())
.andReturn();
MockHttpSession mockHttpSession = (MockHttpSession) result.getRequest().getSession();
this.mockMvc
.perform(get("/success").session(mockHttpSession))
.andExpect(status().isOk());
this.session = mockHttpSession;
}
}

作用域为session 的bean 处理

controller 依赖注入了 作用域为 @Scope(scopeName = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)  的bean

例如

@Component("cuzSessionAttributes")
@Scope(scopeName = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserAttributes implements Serializable { }

JunitTest中,可以从MockHttpSession取出这个bean,然后修改bean的属性,再设置回session,以达到测试分支覆盖率的作用

   @Test
public void testDo() throws Exception {
UserAttributes userAttributes = (UserAttributes )session.getAttribute("scopedTarget.userAttributes");
userAttributes.setSomeThing("abc");
session.setAttribute("scopedTarget.userAttributes",userAttributes);
this.mockMvc
.perform(get("/do")
.session(session)).andExpect(status().isOk());
}

上传文件测试

@Test
public void upload() throws Exception {
InputStream inputStream = this.getClass().getResourceAsStream("/test.xlsx");
MockMultipartFile multipartFile = new MockMultipartFile("txt_file","test.xlsx","multipart/form-data; boundary=----WebKitFormBoundarybF0B6B6hk52YSBvk", inputStream);
MvcResult result = this.mockMvc.perform(
fileUpload("/upload").file(multipartFile).session(session)
)
.andExpect(status().isOk()).andReturn();
}

uploadController

网上流传着一段上传多文件的代码,这段代码mock上传是会转换异常的

 @RequestMapping(value = "/batchUpload", method = RequestMethod.POST)
public Result String batchUpload(HttpServletRequest request) {
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
//*****
}
}

改为这样

   /**
* 上传
*/
@PostMapping(path = "/upload", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Transactional(propagation = Propagation.REQUIRED)
public Result upload(MultipartHttpServletRequest multiRequest) {
Iterator<String> iter = multiRequest.getFileNames();
while (iter.hasNext()) {
MultipartFile file = multiRequest.getFile(iter.next());
//*****
}

文件下载测试

   @Test
public void download() throws Exception {
MvcResult mvcResult = this.mockMvc
.perform(get("/download")
.accept(MediaType.APPLICATION_OCTET_STREAM)
.session(session))
.andExpect(status().isOk()).andReturn();
Assert.assertNotNull(mvcResult.getResponse().getContentAsByteArray());
}

验证码问题

SpringBoot解决方式 Environment

获取环境,这里根据junit环境还有dev环境判断,可以跳过验证码验证

    @Autowired
private Environment env; String active = env.getProperty("spring.profiles.active");
if(!active.equals("junit")&&!active.equals("dev")){

sonar + jacoco + mockMvc 模拟session 用户登录 配合SpringSecurity 权限 快速测试代码覆盖率.的更多相关文章

  1. 写了一个Windows服务,通过C&num;模拟网站用户登录并爬取BUG列表查询有没有新的BUG,并提醒我

    写了一个Windows服务,通过C#模拟网站用户登录并爬取BUG列表查询有没有新的BUG,并提醒我 1.HttpUtil工具类,用于模拟用户登录以及爬取网页: using System; using ...

  2. python入门:模拟简单用户登录(自写)

    #!/usr/bin/env python # -*- coding: utf-8 -*- #模拟简单用户登录(自写) import getpass a = raw_input("Pleas ...

  3. samba共享目录无法访问的一般解决方案,非用户登录和读写权限问题

    配smb,被第四点坑了很久,特此转载. 由于这5点都是比较普通的情况,不涉及用户登录和读写权限问题 1)关闭防火墙: #sevice iptables stop 2)修改 /etc/samba/smb ...

  4. C&num;模拟网站用户登录

    我们在写灌水机器人.抓资源机器人和Web网游辅助工具的时候第一步要实现的就是用户登录.那么怎么用C#来模拟一个用户的登录拉?要实现用户的登录,那么首先就必须要了解一般网站中是怎么判断用户是否登录的. ...

  5. Java--&gt&semi;IO流模拟实现用户登录以及登录信息

    --> Test 测试类 package com.dragon.java.hwlogin; import java.io.FileNotFoundException; import java.u ...

  6. springMVC&plus;request&period;session实现用户登录和访问权限控制

    用springmvc mybatis实现用户登录登出功能,使用session保持登录状态,并实现禁止未登录的用户访问.感谢谷歌资源,在这里做个学习记录加深自己的印象. 原文在我的https://my. ...

  7. &ast;&ast;15&period;app后端怎么设计用户登录方案&lpar;API权限安全&rpar;

    在很多app中,都需要用户的登录操作.登录,就需要用到用户名和密码.为了安全起见,暴露明文密码的次数越少越好.怎么能最大程度避免泄露用户的密码呢?在登录后,app后端怎么去验证和维持用户的登录状态呢? ...

  8. ubuntu使用root用户登录&sol;切换root权限

    ubuntu系统默认root用户是不能登录的,密码也是空的. 如果要使用root用户登录,必须先为root用户设置密码 打开终端,输入:sudo passwd root 然后按回车 此时会提示你输入密 ...

  9. tp5的RBAC插件及其使用很方便的管理用户登录及操作权限

    tp5-rbac 本扩展包是tp5的rbac包,使用了部分tp5的特性实现了关系型数据库中特殊数据结构的处理. 安装方法 先安装composer如果不知道怎么安装使用composer请自行百度. 打开 ...

随机推荐

  1. Is an MTD device a block device or a char device&quest;

    转:http://www.linux-mtd.infradead.org/faq/general.html#L_mtd_what Note, you can find Ukranian transla ...

  2. AIDL实例

    转载声明:原文转自:http://www.cnblogs.com/xiezie/p/5658372.html 什么是AIDL Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进 ...

  3. mongodb环境部署

    mongodb 环境部署 1.环境说明 安装软件:mongodb-linux-x86_64-.tgz 软件安装位置:/usr/local/mongodb 数据存放位置:/var/mongodb/dat ...

  4. 基于wepy和云开发的动漫资讯小程序----233次元

    233次元小程序 # 233次元小程序 项目描述- 基于微信小程序的动漫咨询小程序,采用`wepy`框架开发:- 后台数据采用小程序的云开发存储: 线上体验 部分截图                 ...

  5. Mac上安装mysqlclient的报错

    [背景] 今天我把算把自己的python基础平台从python-3.6.2升级到python-3.7.2,在我安装完python-3.7.2之后,打算在此基础之上安装 mysqlclient的时候报错 ...

  6. Python3实现Win10桌面背景自动切换

    [本文出自天外归云的博客园] 得空写了个自动切换桌面背景图片的小程序.再不写python就要扔键盘了,对vue还有那么一点好感,天天php真是有够烦. 准备工作 准备个文件夹放在桌面上,平时看到什么高 ...

  7. C&sol;C&plus;&plus;中字符串和数字互转小结

    一. 数字 转 char*型 1.sprintf函数(适合C和C++) 示例: char str[50]; int num = 345; sprintf(str,"%d",num) ...

  8. 小白之selenium&plus;python关于cookies绕开登录1

    cookie是存储在本地浏览器目录的一些信息,详细一点的话可以查看度娘,按照我的理解就是将信息存储在本地,访问网站的时候,网站的服务器会优先读取本地目录位置的信息,然后做出相对的反应.这就是为什么有的 ...

  9. Struts2 利用AJAX 导出大数据设置遮罩层

    Struts2 利用AJAX 导出大数据设置遮罩层 需求背景: 每次我们导出excel的时候 ,如果数据量很大,导出花费的时间会很长,页面却有没人任何反应,这个时候用户会认为系统有问题,要么关了页面, ...

  10. 随手练——HDU Safe Or Unsafe (小根堆解决哈夫曼问题)

    HDU 2527 :http://acm.hdu.edu.cn/showproblem.php?pid=2527 哈夫曼树,学完就忘得差不多了,题目的意思都没看懂,有时间复习下,看了别人的才知道是怎么 ...