如何提高单测覆盖率

news2024/9/24 3:26:35

相关工具推荐:

TestMe:用于快速生成测试类

一、抽象一个公共类,将TestMe的配置内容该类MockTest

import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

import java.io.File;
import java.lang.reflect.Method;

/**
 * mock测试
 */
@RunWith(MockitoJUnitRunner.class)
@Slf4j
public abstract class MockTest {

    @Before
    public void init() {
        //公用设置
        Snowflake.init("127.0.0.1", 8080, true);
    }

    /**
     * 当代码中有需要访问某一个文件时,生成一个临时文件
     * @return
     */
    public String getTmpFilePath(){
        try {
            File mockFile = File.createTempFile("mock", ".txt");
            return mockFile.getPath();
        }catch (Exception e){
            log.error("file create error",e);
            return "";
        }
    }

    public File getTmpFile(){
        try {
            File mockFile = File.createTempFile("mock", ".txt");
            return mockFile;
        }catch (Exception e){
            log.error("file create error",e);
            return null;
        }
    }

    /**
     * 当私有方法较大,正常逻辑不好覆盖时,单测私有方法
     * @param obj
     * @param cla
     * @param instance
     * @param methodName
     * @param paramClass
     */
    public void invokeMethod(Object obj, Class cla, Object instance, String methodName,Class paramClass) {
        try {
            getMethod(methodName, cla,paramClass).invoke(instance, obj);
            //模拟失败
            getMethod(methodName, cla,paramClass).invoke(cla.newInstance(), obj);
        } catch (Exception e) {}
    }

    private Method getMethod(String methodName, Class cla, Class paramClass) throws Exception {
        Method method = cla.getDeclaredMethod(methodName, paramClass);
        method.setAccessible(true);
        return method;
    }
}

二、配置TestMe Templates

代码:

#parse("TestMe macros.java")
#set($hasMocks=$MockitoMockBuilder.hasMockable($TESTED_CLASS.fields))
#if($PACKAGE_NAME)
package ${PACKAGE_NAME};
#end

import static org.junit.Assert.*;
import org.junit.Test;
#if($hasMocks)
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.junit.Assert;
import com.替换路径.MockTest
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
#end

#parse("File Header.java")
@RunWith(MockitoJUnitRunner.class)
public class ${CLASS_NAME} extends MockTest{
#renderMockedFields($TESTED_CLASS.fields)

#renderTestSubjectInit($TESTED_CLASS,$TestSubjectUtils.hasTestableInstanceMethod($TESTED_CLASS.methods),$hasMocks)
#if($hasMocks)

    @Before
    public void setUp() {
        MockitoAnnotations.${MockitoMockBuilder.initMocksMethod}(this);
    }
#end
#foreach($method in $TESTED_CLASS.methods)
#if($TestSubjectUtils.shouldBeTested($method))

    @Test
    public void #renderTestMethodName($method.name)(){
#if($MockitoMockBuilder.shouldStub($method,$TESTED_CLASS.fields))
#renderMockStubs($method,$TESTED_CLASS.fields)

#end
        #renderMethodCall($method,$TESTED_CLASS.name)
        Assert.assertNotNull(new Object());

    }
#end
#end
}

 三、代码覆盖率提升技巧

针对所有的bean和枚举进行单测覆盖,可通用配置

import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author awen
 **/
public class CommonBeanTest {
    String CLASSPATH_ALL_URL_PREFIX = "classpath:";

    @Test
    public void beanTest() throws Exception {

        List<String> list = new ArrayList();
        list.add("com.xxx.bean");
        list.add("com.xxx.api");

        for (String path : list) {
            // 包名转路径
            path = path.replaceAll("\\.", "\\/");
            String packageSearchPath = CLASSPATH_ALL_URL_PREFIX + path + "/**/*.class";
            // 获取所有的Pojo类
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
            // 遍历
            for (Resource r : resources) {
                // 获取类名
                String name = r.getURL().getPath();
                name = name.substring(name.indexOf("com"), name.lastIndexOf("."));
                name = name.replaceAll("/", ".");
                // 获取类对象
                Class c = this.getClass().getClassLoader().loadClass(name);
                if(c.isEnum()){
                    enumCover(c);
                }else if(!c.isInterface()){
                    copyBean(c);
                }
            }
        }
    }

    private void copyBean(Class c) throws Exception {
        try {
            // 生成两个实例
            Object dest = c.newInstance();
            Object orig = c.newInstance();
            // 测试toString方法
            dest.toString();
            // 测试Getter Setter方法
            BeanUtils.copyProperties(dest, orig);
        }catch (Exception e){
        }
    }

    private void enumCover(Class c){
        if(c.isEnum()){
            Object[] enumConstants = c.getEnumConstants();
            Object obj = enumConstants[0];

            for(Object enumConstant:enumConstants) {
                enumConstant.toString();
            }
            try{
                Method method = c.getMethod("getByCode",String.class);
                method.invoke(obj,obj.toString());
            }catch (Exception e){
            }

            try{
                Method method = c.getMethod("valueOf",String.class);
                method.invoke(obj,obj.toString());
            }catch (Exception e){}
        }
    }

}

其他技巧:

1、设置类中的私有变量:

ReflectionTestUtils.setField(被测试类实例,"变量",值);

2、实例化ApplicationContext,设置根据类型返回实例:

ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class);
Map<String, 抽象类> map = Maps.newHashMap();
map.put("1",实例);
Mockito.when(applicationContext.getBeansOfType(抽象类.class)).thenReturn(map);

3、类中mock的方法时,如果有重载方法,可使用any(Class)转化为相关类型,再进行处理

when(类实例.方法(any(XXX.class),any(),any())).thenReturn(mock返回值);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/801244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue的4S店车辆管理系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

浅浅了解线程池

线程池 1.线程池基本概念(了解)1.1 什么是线程池1.2 为什么使用线程池1.3 线程池的优势 2.创建池的方式3.线程池的工作原理(重点)3.1 线程池的七大参数3.2 线程池的四种拒绝策略AbortPolicyCallerRunsPolicyDiscardPolicyDiscardOldestPolicy 3.3 任务队列 4. 自定义线程池(代码…

提供实习证明和奖学金!面向本科生、研究生的 AI 夏令营!第二期开放报名

无论你是新手还是有AI基础 只要你对AI方向感兴趣&#xff0c;有热情 欢迎你加入Datawhale AI 夏令营 联合科大讯飞、阿里云天池 面向在校本科生、研究生 提供暑期实践学习机会 第二期正式开放报名 线上活动&#xff0c;全程免费 报名时间&#xff1a;2023/7/26 - 2023/8/1 1 关…

​渔网格及多边形网格(蜂窝图)表现空间分布特征

重新排版新发。渔网格及多边形网格(蜂窝图)表现空间分布特征。 练习数据: 爬取的山东省胶东五市文保单位。 先上结果图 1.渔网图表现空间分布特征 整体步骤是先对数据做核密度分析,用渔网工具创建渔网格与点,然后将核密度的值赋至渔网格上,最后进行一系列可视化表达。 …

抖音seo短视频矩阵系统源代码开发技术分享

抖音SEO短视频矩阵系统是一种通过优化技术&#xff0c;提高在抖音平台上视频的排名和曝光率的系统。以下是开发该系统的技术分享&#xff1a; 熟悉抖音平台的算法 抖音平台的算法是通过分析用户的兴趣爱好和行为习惯&#xff0c;对视频进行排序和推荐。因此&#xff0c;开发人员…

HTML+CSS+JavaScript:实现京东秒杀倒计时效果

一、产品需求 下图是京东首页的京东秒杀倒计时 我们将模仿京东倒计时做一个下班倒计时效果&#xff08;如下图&#xff09; 二、代码素材 我先把缺失JS部分的代码放在这里&#xff0c;感兴趣的小伙伴可以先自己试试 <!DOCTYPE html> <html lang"en">&…

ABB机器人与S7-1200PLC实现位置坐标数据发送和接收的具体方法

ABB机器人与S7-1200PLC实现位置坐标数据发送和接收的具体方法 上次和大家分享了ABB机器人与S7-1200 PLC进行Socket通信时的基本设置和简单编程测试,具体可查阅以下链接中的内容: S7-1200与ABB机器人进行SOCKET通信的具体方法 本次继续和大家分享,通过Socket通信(TCP)实现…

DSA之图(3):图的遍历

文章目录 0 图的遍历1 图的遍历方法1.1 深度优先搜索DFS1.1.1 DFS的思想1.1.2 邻接矩阵DFS的实现1.1.3 邻接矩阵DFS的代码实现1.1.4 非连通图的DFS遍历1.1.5 DFS算法效率分析 1.2 广度优先搜索BFS1.2.1 BFS的思想&#xff08;连通图&#xff09;1.2.2 BFS的思想&#xff08;非连…

【机器学习】分类算法 - 模型选择与调优GridSearchCV(网格搜索)

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;零基础快速入门人工智能《机器学习入门到精通》 模型选择与调优 1、交叉验证2、网格搜索3、模型选择与调优API4、案…

IntelliJ IDEA 2023.2 最新变化

主要更新 AI Assistant 限定访问 Ultimate 在此版本中&#xff0c;我们为 IntelliJ IDEA 引入了一项重要补充 – AI Assistant。 AI Assistant 当前具备一组由 AI 提供支持的初始功能&#xff0c;提供集成式 AI 聊天&#xff0c;可以完成一些任务&#xff0c;例如自动编写文档…

在win10上安装spinal hdl完全教程(一篇文章就够了)

一 参考文章 SpinalHDL 开发环境搭建一步到位(图文版) - 极术社区 - 连接开发者与智能计算生态 (aijishu.com)https://aijishu.com/a/1060000000255643SpinalHDL(一)——环境搭建 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/146529005

Android安卓实战项目(4)---提供给阿尔兹海默症患者的APP(源码在文末)

Android安卓实战项目&#xff08;4&#xff09;—提供给阿尔兹海默症患者的APP&#xff08;源码在文末&#xff09; 一.项目运行介绍 1.大致浏览 &#xff08;1&#xff09;开机界面 &#xff08;2&#xff09;主界面 &#xff08;3&#xff09;Read Instructions界面 &…

运维:Windows11操作系统安装VMware16.1.1图文教程(附下载)

目录 一、VMware 16.1.1 介绍 二、安装教程 三、下载地址 一、VMware 16.1.1 介绍 VMware 16.1.1 是一款功能非常强大虚拟化软件&#xff0c;它允许用户在一台计算机上创建和运行多个虚拟机&#xff08;Virtual Machine&#xff09;相当于拥有多台服务器。这些虚拟机可以模拟…

JUC高并发编程(二)——Synchronized关键字

文章目录 前言为什么要用Synchronized关键字 并发编程中的三个问题可见性原子性有序性 Synchronized保证三大特性使用synchronized保证可见性使用synchronized保证原子性用synchronized保证有序性 Synchronized的特征可重入特征不可中断特征 前言 synchronized 关键字&#xff…

Python爬虫时遇到SSL证书验证错误解决办法汇总

在进行Python爬虫任务时&#xff0c;遇到SSL证书验证错误是常见的问题之一。SSL证书验证是为了确保与服务器建立的连接是安全和可信的&#xff0c;但有时候可能会由于证书过期、不匹配或未受信任等原因导致验证失败。为了解决这个问题&#xff0c;本文将提供一些实用的解决办法…

提高业务效率:利用手机号在网状态 API 进行智能筛选

引言 随着科技的不断发展&#xff0c;手机已成为现代人生活中不可或缺的工具。人们通过手机完成通信、娱乐、购物等各种活动&#xff0c;使得手机号成为了一个重要的个人标识。对于企业而言&#xff0c;了解手机号的在网状态对于业务发展和客户管理至关重要。为了提高业务效率…

https和http有什么区别

https和http有什么区别 简要 区别如下&#xff1a; ​ https的端口是443.而http的端口是80&#xff0c;且二者连接方式不同&#xff1b;http传输时明文&#xff0c;而https是用ssl进行加密的&#xff0c;https的安全性更高&#xff1b;https是需要申请证书的&#xff0c;而h…

Linux常用命令——dpkg-statoverride命令

在线Linux命令查询工具 dpkg-statoverride Debian Linux中覆盖文件的所有权和模式 补充说明 dpkg-statoverride命令用于Debian Linux中覆盖文件的所有权和模式&#xff0c;让dpkg于包安装时使得文件所有权与模式失效。 语法 dpkg-statoverride(选项)选项 -add&#xff1…

深度:解密数据库的诗与远方!

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 不同于历史上的黄金和石油&#xff0c;数据成为了我们新的宝藏&#xff0c;一个驱动社会进步、催生创新的无尽源泉。然而&#xff0c;这些形式各异、复杂纷繁的数据需要一个管理者&#xff0c;一个保险库&#xff0c;一个解…

【动态规划part09】| 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

&#x1f388;LeetCode198.打家劫舍 链接&#xff1a;198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷…