卓越工程之单元测试在行权鉴权中的实践

news2024/11/18 13:42:17

前言

在去年的时候就读过《重构:改善既有代码的设计》这本在代码重构领域里的经典,当时在读的时候就苦于有这么两点导致只停留在了“读”上面,而缺少实践。

1.全书内容比较枯燥乏味,虽然有部分代码示例,但是语言并不生动,让人坚持读下去就很难。

2.书中强调,每做一次代码的重构,即使修改很小的部分,也应该对修改进行测试,所以在看到书中举例的各种重构和重构后的不断测试时,就对测试和重构打起了退堂鼓

因为对代码的测试缺少整体的认知,对单元测试也一直停留在简单的print层面,直到在这几天通过一个阅读打卡活动,系统性的学习了大量关于单元测试的理论、实践知识和在代码重构中的帮助,重新让我回忆起《重构》书中所提到的知识点,一直跃跃欲试,所以也想尝试将单元测试实际应用在自己写的业务代码中,为自己的代码“保驾护航”,同时在代码中有单测,在重构的过程中单测也会让自己不慌张,修改代码后直接执行一下单测就可以对修改后的准确性进行验证。这篇文章着重在“实践”上,是对Java编程技巧之单元测试用例编写流程这篇文章的实际应用,并没有高深的理论和技术。

流程

包括单元测试在内的所有测试都应该对所需要测试的流程有比较清晰的认识才能保证测试的用例不被遗漏,保证测试质量,因此在撰写单元测试前,首先需要对所测试部分代码的流程进行梳理。

1.用户发起查询时,首先判断用户传入的参数中是否包含行权验证的字段,如果不包含则直接抛出异常,提示鉴权失败;

2.在鉴权中,因为行权可能会由多个字段组合鉴权,因此需要对全部鉴权字段进行遍历。在鉴权时,还会有匹配字段,包含:

  • 等值匹配(=)
  • 前缀匹配(like xxx%)
  • 后缀匹配(like %xxx)
  • 模糊匹配(like %xxx%)

四种形式,当用户输入参数与匹配字段不相符时,记作鉴权失败。

3.当用户没有输入参数中的权限时,记作鉴权失败。

4.在多个鉴权字段进行组合时,还会存在两种组合逻辑:and(所有字段均需要有权限才能访问)和 or(任意字段有权限即可访问),所以还会结合组合逻辑进行综合权限判定。

测试边界

在明确了代码的流程后,就需要对测试边界进行明确,测试应该着重对边界情况进行测试,因为清晰的单元测试边界划分有利于构建更加稳定的系统核心代码,因为我们在推进测试边界的过程中会不断地将副作用从核心代码中剥离出去,最终会得到一个完整且可测试的核心,而我们的核心代码就是处于测试边界内的。下图将所有的情况做了枚举,作为单元测试的用例。

撰写单元测试

引入依赖

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-core</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>

其中,powermock.version为2.0.9,为当前的最新版本,可根据实际情况修改。在PowerMock包中,已经包含了对应的Mockito和JUnit包,所以无需单独引入Mockito和JUnit包。

模拟方法

1.首先是需要对外部依赖和进行测试的类进行模拟和注入:

   // 需要模拟的外部依赖
    @Mock
    private ArkDataSetReadService arkDataSetReadService;
    
    // 需要进行测试的类
    @InjectMocks
    private ComponentJobExecuteService componentJobExecuteService;

2.之后就是对依赖的方法进行模拟:

Response<RowPermissionQueryResponseDto> response = JSON.parseObject(permissionData, Response.class);

Mockito.doReturn(response).when(arkDataSetReadService).getUserRowPermissions(911L, 1741141);

●通过文本的方式构造模拟的返回值。

●通过Mockito.doReturn() 方法模拟调用时的返回值。

3.最后就是对所测试的方法进行测试:

Map<String, Pair<String, List<String>>> filterParams = new HashMap<>();


Whitebox.invokeMethod(componentJobExecuteService, "checkRowPermission", 911L, filterParams)

完整的测试代码:

@Test(expected = AuthException.class)
    public void testRowPermission() throws Exception {
       
        ContextInfo contextInfo = new ContextInfo();
        contextInfo.setBucId(1741141);
        ContextInfoHolder.setContextInfo(contextInfo);
       
        Response<RowPermissionQueryResponseDto> response = JSON.parseObject(permissionData, Response.class);

        Mockito.doReturn(response).when(arkDataSetReadService).getUserRowPermissions(911L, 1741141);

        Map<String, Pair<String, List<String>>> filterParams = new HashMap<>();

        Whitebox.invokeMethod(componentJobExecuteService, "checkRowPermission", 911L, filterParams);
    }

因为在没有权限的时候会直接抛出 AuthException,所以通过@Test(expected = AuthException.class) 进行验证。

到此,行权验证的单元测试框架就初步搭建完成,接下来就是根据前面梳理的单元测试用例的边界构建不同的参数进行验证。

总结

在实际撰写单元测试时,由于对工具的不熟悉担心写起来比较麻烦,所以一直没进行尝试,但是在实际操作的时候发现,在写单元测试的时候,其实也是对整个代码进行梳理的过程,是对自己写代码时思路的复盘和总结,单测不只是能验证代码执行的准确性,还能验证在写代码时的逻辑是否正确、能否满足业务的实际需求。

有了单测打底,接下来即使需要对这部分代码进行重构、迭代,也能做到心中有数,只需要在重构完成后执行下单测就可以轻松验证代码的准确性。

希望能够通过这次实践,能够让自己在写单测的路上坚持下去。

作者 | 邱庆羽(羽哲)

原文链接

本文为阿里云原创内容,未经允许不得转载。

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

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

相关文章

新能源车的火烧到了二手车市场

今年以来&#xff0c;新能源二手车市场有明显回暖的迹象。据中国汽车流通协会数据显示&#xff0c;今年上半年&#xff0c;新能源二手车交易量达15.6万辆&#xff0c;同比增长36.4&#xff05;&#xff0c;比传统燃油车增速高出24.5个百分点。另据瓜子二手车大数据显示&#xf…

Android平台GB28181设备接入端预置位查询(PresetQuery)探讨和技术实现

之前blog介绍了GB28181云台控制&#xff08;PTZCmd&#xff09;相关&#xff0c;本文主要是介绍下GB28181预置位查询。 预置位这块&#xff0c;在处理带云台的设备非常必要&#xff0c;我们主要是做Android平台的GB28181的设备接入端&#xff0c;也可以转发RTSP摄像头接入到国…

F3--FPGA读写EEPROM实例2022-12-12

1.EEPROM简介 EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。在嵌入式控制系统中常常用来保存设备初始化所需数据。发展过程&#xff1a;ROM – > PROM –> EPROM –> EEPROM&…

移动Web基础知识点大全

移动Web基础知识点大全移动Web1、字体图标2、平面转换3、渐变4、空间转换5、动画6、移动端特点7、百分比布局8、Flex布局9、移动适配9.1 rem9.2 less9.3 vw/vh10、媒体查询11、BootStrap移动Web 1、字体图标 目标&#xff1a;使用字体图标实现网页中简洁的图标效果字体图标 字…

数据技术篇之实时技术

第5章 实时技术 在大数据系统中&#xff0c;离线批处理技术可以满足非常多的数据使用场景需求&#xff0c;但在 DT 时代&#xff0c; 每天面对的信息是瞬息万变的&#xff0c;越来越多的应用场景对数据的时效性提出了更高的要求。数据价值是具有时效性的&#xff0c;在一条数据…

霸榜,这本《程序员如何向架构师转型》在Github已持续置顶两月

前言 企业架构在过去十年中取得了长足的进步。随着越来越多新技术出现&#xff0c;充分利用这些因素来将企业架构创建得更好十分重要。通过将新技术集成到企业架构中&#xff0c;即使在困难时期&#xff0c;也能取得丰硕的成果。 现代企业架构师的 5 个特征&#xff1a; 1. …

移动端插件-IScroll列表滑动、区块滑动

iScrol l是一个高性能&#xff0c;资源占用少&#xff0c;无依赖&#xff0c;多平台的javascript滚动插件(4kb)。 官方&#xff1a; iScroll 访问不了 (iscrolljs.com) iScroll github (https://github.com/cubiq/iscroll) -> build 文件夹 包含各个版本 iScroll 中文…

国内智能手表行业数据浅析

大家好&#xff0c;这里是小安说网控。 智能手表&#xff0c;作为智能穿戴的一种&#xff0c;大大方便了人们的生活。 2022年9月份&#xff0c;我国智能手表产量当期值695.6万个&#xff0c;同比增长21.4%&#xff1b;10月份当期值为552.6万个&#xff0c;同比下滑16.5%。1-10月…

宝塔面板打不开怎么登录进入宝塔页面

浏览器新建标签页&#xff0c;输入服务器公网地址ip&#xff0c;后面加:8888&#xff0c;例如 1.2.3.4:8888 &#xff08;服务器公网地址IP可在云服务器 → 实例→公网IP 查看&#xff09; 删除默认用户名&#xff0c;创建设置你的用户名和密码&#xff0c;确定&#xff0c;登陆…

基于不可否认技术的珍贵古籍线上交易系统设计与实现(JavaWeb的图书商城系统)

目 录 摘 要 I ABSTRACT I 引言 1 1 绪论 1 1.1 课题背景与意义 1 1.2 本文的总体结构 1 2 开发工具及技术 2 2.1 开发工具 2 2.1.1 前台使用技术 2 2.1.2 后台使用技术 2 2.1.3 后端使用技术 3 2.2 B/S架构 3 2.3 软硬件需求 3 3 系统的需求分析和概要设计 3 3.1 可行性分析 3…

IPv6升级转换最新消息,全在这一篇了!-中科三方

工信部部长苗圩&#xff1a;加快“双千兆”建设&#xff0c;提升IPv6网络服务能力 工信部部长苗圩在第19届中国互联网大会上指出&#xff0c;过去一年&#xff0c;互联网行业扎实推进各项工作&#xff0c;在基础设施建设、产业实力提升、融合应用深化等方面不断取得新的…

JavaSE03

Idea中自动生成构造器和get,set的快捷键&#xff1a;altinsert 关于继承的访问&#xff1a; this和super的用法&#xff1a; 子类中的所有构造方法默认都会访问父类中无参构造方法 重写&#xff1a; 重写注意&#xff1a;1.父类中的私有方法&#xff0c;子类不能重写。2.子…

火遍全网的chatGPT(文末有彩蛋)

最近网上非常火爆的CHATGPT&#xff0c;它是OpenAI开发的一款开源的自然语言处理 (NLP) 模型&#xff0c;用于实现对话生成和语言模型预测。CHATGPT 模型基于 GPT-3 (Generative Pretrained Transformer 3) 模型构建&#xff0c;拥有语言理解和文本生成能力。CHATGPT 模型可以用…

分库分表、Memory引擎、代理逐渐、主从复制、IP直连问题

文章目录几千万数据量大表做MySQL主从崩了&#xff0c;该如何优化&#xff1f;为啥禁用IP直连为啥主键使用代理主键&#xff0c;而不是业务主键报表分析使用ESExplain 可视化Visual_Explain一致性Hash解决MySQL分库库容问题不建议在 Docker 中跑 Mysql优雅地进行数据归档倒排索…

《自己动手写CPU》学习记录(8)——第7章/Part 1

目录 引言 致谢 指令说明 add、addu、sub、subu、slt、sltu addi、addiu、slti、sltiu clo、clz multu、mult、mul 设计 宏定义 译码模块 指令执行模块 仿真 仿真程序 仿真结果 引言 随章节进度继续推进&#xff0c;本章继续实现 算术运算 指令等其他操作指令。…

CVPR2020-Meshed-Memory Transformer for Image Captioning

论文地址&#xff1a;Meshed-Memory Transformer for Image Captioning (thecvf.com) Background 本文在transformer的基础上&#xff0c;对于Image Caption任务&#xff0c;提出了一个全新的fully-attentive网络。在此之前大部分image captioning的工作还是基于CNN进行特征提…

error: (-215:Assertion failed) !ssize.empty() in function ‘cv::resize‘

网上以及说来很多方法了&#xff0c; 1.图片路径写成了如下形式&#xff1a;C:\Users\Desktop\test 正确的应该为&#xff1a;C:/Users/Desktop/test/ &#xff08;在程序中斜杠‘\’有转义字符含义&#xff09; 2.图片路径少写了一个斜杠&#xff08;图片存放在test文件夹中&…

深度强化学习

参考1. 引言 — 动手学深度学习 2.0.0 documentation 深度强化学习&#xff08;deep reinforcement learning&#xff09;将深度学习应用于强化学习的问题&#xff0c;是非常热门的研究领域。 突破性的深度Q网络&#xff08;Q-network&#xff09;在雅达利游戏中仅使用视觉输入…

easy-jenkins自动化部署

项目简介 easy-jenkins是一款可以对本地项目进行一键自动化部署的一款简易工具,可以很方便地将平常我们java开发中的springboot项目自动打包成jar包以及vue等前端项目也进行一键构建上传服务器进行部署,更加简化了jenkins的繁琐配置,对于使用者来说更加友好与方便 我们在使用时…