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

简介: 这篇文章着重在“实践”上,是对Java编程技巧之单元测试用例编写流程这篇文章的实际应用,并没有高深的理论和技术。

前言

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

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

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

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


流程

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

image.png

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

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

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

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

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

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


测试边界

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

image.png


撰写单元测试


引入依赖

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


总结

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

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

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


作者 | 邱庆羽(羽哲)

来源 | 阿里云开发者公众号

相关文章
|
5天前
|
敏捷开发 机器人 Java
自动化测试之美:从理论到实践
【9月更文挑战第28天】在软件开发的海洋中,自动化测试是一艘航向高效、精确和快速交付的船。它不仅减轻了手动测试的负担,还提升了软件质量的保障。本文将带你了解自动化测试的核心概念、流行的工具以及如何将这些理论应用到实践中去。我们将通过实际代码示例,探索自动化测试的魅力所在。
109 70
|
5天前
|
测试技术
探索软件测试的奥秘:从基础理论到实践应用
【9月更文挑战第28天】在数字化时代,软件已成为我们生活中不可或缺的一部分。然而,随着软件复杂性的增加,确保其质量和可靠性变得日益重要。本文将带你深入了解软件测试的核心概念、方法论以及如何在实际工作中运用这些知识来提升软件质量。无论你是软件测试新手还是希望深化理解,这篇文章都将为你提供宝贵的洞见和实用技巧。
|
3天前
|
Devops jenkins 测试技术
DevOps实践:持续集成与自动化测试的融合之道
【9月更文挑战第29天】在软件开发的快节奏竞赛中,DevOps如同一位智慧的舵手,引领着船只驶向效率与质量的彼岸。本文将揭开DevOps的神秘面纱,探索其核心理念如何通过持续集成(CI)和自动化测试的实践,实现软件开发流程的优化与加速。我们将一同见证代码从构思到部署的旅程,以及这一过程中的关键技术和工具如何协同工作,确保软件质量和交付速度的双重提升。
|
7天前
|
敏捷开发 监控 测试技术
提升软件质量的利器:自动化测试的实践与反思
在软件开发的生命周期中,测试作为保障产品质量的重要环节,其重要性不言而喻。随着敏捷开发和持续集成等实践的普及,传统的手动测试方式已逐渐无法满足快速迭代的需求。因此,自动化测试作为一种提高测试效率和准确性的有效手段,正受到越来越多开发者的青睐。本文将深入探讨自动化测试的价值、实施步骤以及在实践中可能遇到的问题和解决方案,帮助读者更好地理解和应用自动化测试。
12 2
|
11天前
|
Web App开发 JavaScript Java
自动化测试的利剑:Selenium WebDriver入门与实践
【9月更文挑战第21天】在软件开发的海洋中,自动化测试犹如一艘船,帮助开发者们快速航行至质量保证的彼岸。本文将作为你的罗盘,指引你了解和掌握Selenium WebDriver这一强大的自动化测试工具。通过深入浅出的方式,我们将探索Selenium WebDriver的基本概念、安装过程以及编写简单测试脚本的方法。无论你是刚接触自动化测试的新手,还是希望提升测试技能的开发者,这篇文章都将为你提供有价值的指导。
|
11天前
|
监控 安全 测试技术
软件测试的艺术:探索式测试的魅力与实践
【9月更文挑战第21天】在软件开发的海洋中,测试是确保航行安全的灯塔。本文将带你领略探索式测试(Exploratory Testing)的独特魅力,这是一种强调个人技能和经验、鼓励即兴发挥的测试方式。我们将通过实际案例,探讨如何有效实施探索式测试,以及它如何与传统测试方法相辅相成,共同提升软件质量。
|
9天前
|
存储 安全 jenkins
提升软件测试效率的策略与实践
在软件开发过程中,测试环节扮演着至关重要的角色。它不仅保障了软件产品的质量,还在很大程度上决定了产品的最终用户体验。本文将探讨几种实用的策略和实践方法,旨在提高软件测试的效率。从自动化测试工具的应用,到持续集成环境的搭建,再到测试用例的高效管理,我们将一一解析如何优化测试流程,减少重复工作,确保软件质量的同时,缩短上市时间。
|
6天前
|
小程序 测试技术 程序员
『软件工程12』软件工程实践方法——软件测试
该文章详细阐述了软件测试的重要性和基本原则,并按测试阶段顺序介绍了单元测试、集成测试、确认测试以及系统测试的具体内容和实施步骤。
『软件工程12』软件工程实践方法——软件测试
|
9天前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
|
11天前
|
测试技术
软件测试中的自动化策略与实践
【9月更文挑战第21天】在软件开发的生命周期中,测试阶段扮演着至关重要的角色。它不仅确保了软件产品的质量,还帮助团队及早发现并修复缺陷,从而节省时间和成本。本文将探讨如何通过实施自动化测试策略来提升测试效率和有效性,包括选择合适的工具、设计有效的测试用例以及维护测试脚本。文章旨在为读者提供一套清晰的指导方针,帮助他们在项目中成功地应用自动化测试。
下一篇
无影云桌面