【Maven】本地执行一个模块的UT失败,但是线上能执行成功

2023-10-12 16:52

本文主要是介绍【Maven】本地执行一个模块的UT失败,但是线上能执行成功,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

在一个工程项目中,往往我们都需要针对新写的代码补充 UT.
基于此,我们每次进一次新的代码,比较好的习惯就是用新的 UT 去覆盖或者旧的UT 去覆盖掉当前新写的 代码。

而就在最近,发现有 UT 不管在本地清理缓存之后,依旧执行失败,但是在线上却都能每次都成功。
并且两边的 UT 执行都是串行的,所以可以很确定的说,这个 UT 肯定在本地有上下文影响的。

原因定位

串行执行,但是顺序不一样?

在确定了串行执行的之后,发现,既然都是串行的,线上和本地的电脑执行的 maven 版本也都对齐了都情况下。

对齐 maven 版本,是为了避免再次遇到奇奇怪怪的问题,在定位问题的时候,如果没有太多的上下文,那么对齐测试步骤和使用工具版本是非常有必要的。

理论上,两边的执行case 的顺序也应该是一样的。
但是很不幸,使用脚本快速确认两边执行的测试用例的顺序是不一样。
预期失败的 case 是在本地最后一个执行的,而在线上 却是在中间就执行了。

万幸的是,确定了顺序是不一样,那么就很快确定,其实影响了case 范围我们也能确定下来。

排除了线上能执行通过的前置的那些case,那么剩下的case 肯定就是能影响到了。

到底是哪个case 影响到了?

确定了影响的范围的 case 到底是哪些呢?是一个还是两个?

一个简单的做法其实就是二分法,将剩下的 影响的case 一半 disable或者说是skip 掉,然后重跑,逐渐缩小其范围,当然我们可以写脚本去触发 ut 执行即可。

最终,确定了影响的case 竟然是这样写代码!

@Test
public void testA() {...MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class));utilities.when(StaticUtils::name).thenReturn("Eugen");assertThat(StaticUtils.name()).isEqualTo("Eugen")...
}

有小伙伴看出是什么问题了吗?!

对,乍一看好像什么都没错,但是实际上这个是有大问题的!

因为根据 Maven 官方一些使用文档,着重提醒了如下内容!
参考文档:
maven 使用手册:关于 static mocks
Mocking Static Methods With Mockito

As previously mentioned, since Mockito 3.4.0, we can use the Mockito.mockStatic(Class classToMock) method to mock invocations to static method calls. This method returns a MockedStatic object for our type, which is a scoped mock object.

Therefore, in our unit test above, the utilities variable represents a mock with a thread-local explicit scope. It’s important to note that scoped mocks must be closed by the entity that activates the mock. This is why we define our mock within a try-with-resources construct so that the mock is closed automatically when we finish with our scoped block.

意思简单翻译下就是:如果要用 mock static 那么请注意使用 try-with-resources 的方式,不要让其影响到整个测试流程!

@Test
public void testA() {...try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class))) {utilities.when(StaticUtils::name).thenReturn("Eugen");assertThat(StaticUtils.name()).isEqualTo("Eugen")}...
}

总结

这个 mock static 影响的非常大,但是藏着又特别深,在非常多的 case 当中去找到影响的 case 是非常费力又不讨好的事情。
所以,千万谨记,如果要用相关的 测试方式,请查看人家的官网测试手册给到的建议!!!

番外

为什么线上的 maven 和 本地的maven 的执行 ut case 顺序不一样?
原因在于,线上的执行命令修改了,并且用的排序方式是使用执行测试的方法名字典序排列。
而本地执行顺序是以执行方法类的字典序排列。
这就是一开始的差异点。

这篇关于【Maven】本地执行一个模块的UT失败,但是线上能执行成功的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/197183

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Java实现远程执行Shell指令

《Java实现远程执行Shell指令》文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别... 目录软硬件环境说明编写执行Shell指令的工具类总结jsch(Java Secure Channel)是SSH2的一个纯J

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Java实现本地缓存的四种方法实现与对比

《Java实现本地缓存的四种方法实现与对比》本地缓存的优点就是速度非常快,没有网络消耗,本地缓存比如caffine,guavacache这些都是比较常用的,下面我们来看看这四种缓存的具体实现吧... 目录1、HashMap2、Guava Cache3、Caffeine4、Encache本地缓存比如 caff