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

背景

在一个工程项目中,往往我们都需要针对新写的代码补充 UT.

基于此,我们每次进一次新的代码,比较好的习惯就是用新的 UT 去覆盖或者旧的UT 去覆盖掉当前新写的 代码。

而就在最近,发现有 UT 不管在本地清理缓存之后,依旧执行失败,但是在线上却都能每次都成功。

并且两边的 UT 执行都是串行的,所以可以很确定的说,这个 UT 肯定在本地有上下文影响的。

原因定位

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

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

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

理论上,两边的执行case 的顺序也应该是一样的。

但是很不幸,使用脚本快速确认两边执行的测试用例的顺序是不一样。

预期失败的 case 是在本地 最后一个执行的,而在线上 却是在中间就执行了。

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

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

到底是哪个case 影响到了?

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

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

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

java 复制代码
@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 的方式,不要让其影响到整个测试流程!

java 复制代码
@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 顺序不一样?

原因在于,线上的执行命令修改了,并且用的排序方式是使用执行测试的方法名字典序排列。

而本地执行顺序是以执行方法类的字典序排列。

这就是一开始的差异点。

相关推荐
π大星星️30 分钟前
基于LNMP架构的个人博客系统部署
服务器·架构
Chase_Mos3 小时前
Spring 必会之微服务篇(1)
java·spring·微服务
小林学习编程6 小时前
SpringBoot校园失物招领信息平台
java·spring boot·后端
撸码到无法自拔6 小时前
docker常见命令
java·spring cloud·docker·容器·eureka
heart000_16 小时前
IDEA 插件推荐:提升编程效率
java·ide·intellij-idea
菜菜why7 小时前
AutoDL租用服务器教程
服务器
IT专业服务商7 小时前
联想 SR550 服务器,配置 RAID 5教程!
运维·服务器·windows·microsoft·硬件架构
ŧ榕树先生7 小时前
查看jdk是否安装并且配置成功?(Android studio安装前的准备)
java·jdk
未来的JAVA高级开发工程师7 小时前
适配器模式
java
LUCIAZZZ7 小时前
JVM之内存管理(一)
java·jvm·spring·操作系统·springboot