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

简介: 这篇文章着重在“实践”上,是对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) 进行验证。到此,行权验证的单元测试框架就初步搭建完成,接下来就是根据前面梳理的单元测试用例的边界构建不同的参数进行验证。


总结

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

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

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


作者 | 邱庆羽(羽哲)

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

相关文章
|
8天前
|
jenkins 测试技术 持续交付
提升软件测试效率的创新实践
在软件开发过程中,测试环节扮演着至关重要的角色。本文探讨了如何通过创新的方法和工具,提高软件测试的效率和质量。我们将从自动化测试、持续集成与持续部署(CI/CD)、测试驱动开发(TDD)三个方面,详细介绍这些技术如何改变传统的测试流程,帮助团队更快地发现和修复缺陷,最终实现更高质量的软件交付。
121 67
|
12天前
|
SQL 测试技术 持续交付
探索软件测试的多维度——从理论到实践
【9月更文挑战第35天】在软件工程的世界中,测试是一个不可或缺的环节。它不仅保障了软件产品的质量,而且确保了用户体验的一致性和可靠性。本文将从不同的角度切入,探讨软件测试的多个方面,包括测试的目的、类型、工具以及最佳实践。通过深入浅出的方式,我们旨在为读者提供一个全面的测试知识框架,帮助他们更好地理解并执行软件测试工作。
25 2
|
19天前
|
敏捷开发 机器人 Java
自动化测试之美:从理论到实践
【9月更文挑战第28天】在软件开发的海洋中,自动化测试是一艘航向高效、精确和快速交付的船。它不仅减轻了手动测试的负担,还提升了软件质量的保障。本文将带你了解自动化测试的核心概念、流行的工具以及如何将这些理论应用到实践中去。我们将通过实际代码示例,探索自动化测试的魅力所在。
122 70
|
19天前
|
测试技术
探索软件测试的奥秘:从基础理论到实践应用
【9月更文挑战第28天】在数字化时代,软件已成为我们生活中不可或缺的一部分。然而,随着软件复杂性的增加,确保其质量和可靠性变得日益重要。本文将带你深入了解软件测试的核心概念、方法论以及如何在实际工作中运用这些知识来提升软件质量。无论你是软件测试新手还是希望深化理解,这篇文章都将为你提供宝贵的洞见和实用技巧。
|
3天前
|
测试技术
软件测试中的探索性测试(ET)实践
【10月更文挑战第5天】本文将深入探讨一种与传统脚本化测试不同的测试方法——探索性测试(Exploratory Testing,简称ET)。我们将通过一个实际案例来展示ET的有效性,并分享如何将ET融入日常的软件测试流程中。文章旨在为测试人员提供一种灵活、高效的测试策略,帮助他们更好地发现软件中的缺陷。
|
2天前
|
机器学习/深度学习 人工智能 监控
提升软件质量的关键路径:高效测试策略与实践在软件开发的宇宙中,每一行代码都如同星辰般璀璨,而将这些星辰编织成星系的过程,则依赖于严谨而高效的测试策略。本文将引领读者探索软件测试的奥秘,揭示如何通过精心设计的测试方案,不仅提升软件的性能与稳定性,还能加速产品上市的步伐,最终实现质量与效率的双重飞跃。
在软件工程的浩瀚星海中,测试不仅是发现缺陷的放大镜,更是保障软件质量的坚固防线。本文旨在探讨一种高效且创新的软件测试策略框架,它融合了传统方法的精髓与现代技术的突破,旨在为软件开发团队提供一套系统化、可执行性强的测试指引。我们将从测试规划的起点出发,沿着测试设计、执行、反馈再到持续优化的轨迹,逐步展开论述。每一步都强调实用性与前瞻性相结合,确保测试活动能够紧跟软件开发的步伐,及时适应变化,有效应对各种挑战。
|
3天前
|
Web App开发 设计模式 测试技术
自动化测试框架的搭建与实践
【10月更文挑战第5天】本文将引导你理解自动化测试框架的重要性,并通过实际操作案例,展示如何从零开始搭建一个自动化测试框架。文章不仅涵盖理论,还提供具体的代码示例和操作步骤,确保读者能够获得实用技能,提升软件质量保障的效率和效果。
|
6天前
|
测试技术 持续交付 Python
软件测试中的自动化策略与实践
【10月更文挑战第2天】在软件开发的海洋中,自动化测试如同一座灯塔,为追求高效率和高质量的航程提供方向。本文将深入探讨自动化测试的策略与实践,从基础理论到实际应用,带领读者领略自动化测试的魅力和挑战。
|
6天前
|
敏捷开发 jenkins 测试技术
自动化测试框架的设计与实践
【10月更文挑战第2天】在软件开发周期中,测试阶段扮演着至关重要的角色。随着敏捷开发和持续集成的流行,自动化测试已成为确保软件质量和加快交付速度的关键工具。本文将深入探讨自动化测试框架的设计原则、组件选择、以及实现过程。通过实际案例分析,我们不仅展示了如何构建一个健壮的自动化测试框架,还讨论了如何克服常见问题,并提出了优化策略,以帮助读者更好地理解自动化测试的价值和实施细节。
|
8天前
|
敏捷开发 监控 测试技术
深入理解自动化测试:从理论到实践
自动化测试在软件开发中扮演着至关重要的角色,它不仅提高了测试效率,还确保了软件质量的一致性和可靠性。本文将引导你了解自动化测试的核心概念,探讨其在不同开发阶段的应用,并通过一个简单的代码示例,展示如何实现一个基本的自动化测试脚本。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用的技能。