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

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

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#模拟网站用户登录并爬取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#模拟网站用户登录

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

  5. Java-->IO流模拟实现用户登录以及登录信息

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

  6. springMVC+request.session实现用户登录和访问权限控制

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

  7. **15.app后端怎么设计用户登录方案(API权限安全)

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

  8. ubuntu使用root用户登录/切换root权限

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

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

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

随机推荐

  1. Servlet--取得session,application内置对象

    在前面的博客里面,使用Servlet取得了request,response,config对象,实际上通过Servlet程序也可以取得session,application等内置对象. 1,通过Http ...

  2. CSS中设置border:none和border:0的区别

    在我们设置CSS的时候,对标签元素不设置边框属性或者取消边框属性一般设置为:border:none;或border:0;两种方法均可. border:none;与border:0;的区别体现有两点:一 ...

  3. CSS继承、层叠和特殊性

    1.继承 (1)样式应用于某个特定的HTML标签元素,而且应用于其后代. (2)但某些标签不适用,如border: (3)例子:p{color:red;}设置了颜色 <p class=" ...

  4. plus、max、Pro、Edge

    plus.max.Pro.Edge等后缀到底什么意思? Plus:比好更好.比牛X更牛X 译成中文是:加.和.正的-的意思.比如oneplus中文名就是一加.用于手机命名表示配置更加牛X,最早是由iP ...

  5. 锐捷配置telnet

    .组网需求 通过Telnet功能远程登录管理设备.   二.组网拓扑   三.配置要点 1.需要给交换机配置一个管理IP,如果PC与交换机不是同一个网段,需要给交换机配置一个默认网关 2.需要配置一个 ...

  6. 浅尝一个排程引擎Optaplanner,前序。

    当码农有10多年了,由建筑行业软件,各种MIS,通用物流定制平台,CCTV客户端(是闭路电视,不是央视喔)啥都做过.最后小试一下创业,不过那都是闹着玩的,不到一年就回到码农的队列,重拾搬砖的行当.近些 ...

  7. 浏览器中页面的visibility状态及变化监听

    需求 在浏览器中播放视频,当用户进行页面切换操作时.需要根据视频播放页是否处于可见状态,来控制视频的暂停及重新播放. 相关文档 参考MDN中,关于页面的可见性相关的API说明.https://deve ...

  8. Django REST framework反向生成url

    Django REST framework是一个基于Django的框架,REST framework又是怎么反向生成url的呢?? 在前面的例子中,知道在REST framework中有6种版本控制的 ...

  9. 单元测试系列:Mock工具Jmockit使用介绍

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6760272.html Mock工具Jm ...

  10. python 3.x 爬虫基础---http headers详解

    前言 上一篇文章 python 爬虫入门案例----爬取某站上海租房图片 中有对headers的讲解,可能是对爬虫了解的不够深刻,所以老觉得这是一项特别简单的技术,也可能是简单所以网上对爬虫系统的文档 ...