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

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

科技


前言


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

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

总结


在实际撰写单元测试时,由于对工具的不熟悉担心写起来比较麻烦,所以一直没进行尝试,但是在实际操作的时候发现,在写单元测试的时候,其实也是对整个代码进行梳理的过程,是对自己写代码时思路的复盘和总结,单测不只是能验证代码执行的准确性,还能验证在写代码时的逻辑是否正确、能否满足业务的实际需求。
有了单测打底,接下来即使需要对这部分代码进行重构、迭代,也能做到心中有数,只需要在重构完成后执行下单测就可以轻松验证代码的准确性。
希望能够通过这次实践,能够让自己在写单测的路上坚持下去。

往期推荐

1.聊一聊分布式锁的设计模型

2.阿里10年沉淀|那些技术实战中的架构设计方法


《Java工程师必读手册》


工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工匠精神”——一种追求“以术得道”的精神。如果一个工匠只满足于“术”,不能追求“术”到极致去悟“道”,那只是一个靠“术”养家糊口的工匠而已。作者根据多年来的实践探索,总结了大量的Java编码之“术”,试图阐述出心中的Java编码之“道”。


点击阅读原文查看详情。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
潞晨科技实习生招聘:AIGC大模型算法工程师、AI编译器开发工程师、前端开发工程师等国际劳工组织国际培训中心全球青年论坛2023 (冬季版)“青年实现2030可持续发展议程之先锋”学员招募及选拔通知《部队大院的八零后》第一章 失败的初次邂逅现代汉服面料分类大全法拉盛民间巡逻队在行动!因纽约治安恶化 每晚7-9点护送妇女和老人回家保护老年人和新冠高危人群丨卫健委、中国医药和家庭,都在行动!阿里云块存储团队软件工程实践在行驶的车中,人和球都以和车速一样移动,向上抛出的球会落到哪里?鼓励有雄心的医生科学家,多国在行动、美国在挖人!《部队大院的八零后》第三章 律政俏佳人理性主义的实践者:德国gmp建筑事务所创始合伙人冯·格康教授逝世看《明日战记》,想起《三叶草在行动》 | 科技袁人英国私校的实践活动有多野?!七橡树中学10年级学生去冰岛探险了!宏景智驾校招:图像算法工程师、决策规划算法工程师、SLAM建图算法工程师等德州男子在行进货车顶跳舞自拍,下秒“高速撞高架桥”死亡画面曝光本周一场大风暴席卷南加州!洛杉矶三名卧底人员在行动中乔装成妓女,15人因涉嫌嫖娼人被捕蚂蚁规模化平台工程实践两年多,我们学到了什么厚德E行丨清华经管EMBA四川校友会抗疫志愿服务在行动一年 100% 云原生化,众安保险架构演进的探索与实践 | 卓越技术团队访谈录她在这里度过了后半生券业在行动!五家头部券商集体发声,透露什么信号?每日10点、12点、20点!防疫物资全力保供,京东健康在行动!俄罗斯吃够亏了,俄版“星链”计划开始,中国也在行动One UI 5.0新测试版本发布,折叠屏率先开放测试无预警动态兑换袭来,我最喜欢的里程之一也开始悄悄贬值了……重磅全文 | 英国ICO《儿童隐私的设计:在线服务的实践准则》博鳌亚洲论坛:可持续发展的亚洲与世界2022年度报告:绿色转型亚洲在行动(106页)拿破仑:政治与军事的实践才能挑战极限突围电商大促场景,得物在高可用上的探索与实践 | 卓越技术团队访谈录大家聊巨变丨“一江一河”成为“人民城市”重要理念的实践地守护网络安全 他们在行动“贝佐斯经济学”的实践与隐忧 |《财经》书摘《部队大院的八零后》第二章 阿联酋的中国空姐涉案企业合规检察建议的实践样态与3大完善进路夺回失去的三年!从总理到地方政府都在行动!
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。