目录

【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 顺序不一样?

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

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

这就是一开始的差异点。

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
Yan-英杰3 分钟前
【百日精通JAVA | SQL篇 | 第三篇】 MYSQL增删改查
java·数据库·sql
矛取矛求1 小时前
C++ 标准库参考手册深度解析
java·开发语言·c++
cijiancao1 小时前
23 种设计模式中的解释器模式
java·设计模式·解释器模式
南七行者1 小时前
对模板方法模式的理解
java·设计模式·模板方法
麻芝汤圆2 小时前
MapReduce 的广泛应用:从数据处理到智能决策
java·开发语言·前端·hadoop·后端·servlet·mapreduce
努力的搬砖人.2 小时前
java如何实现一个秒杀系统(原理)
java·经验分享·后端·面试
哈哈哈哈哈哈哈哈哈...........2 小时前
【java】在 Java 中,获取一个类的`Class`对象有多种方式
java·开发语言·python
fallwind_of_july2 小时前
java项目分享-分布式电商项目附软件链接
java·redis·分布式·mongodb·elasticsearch·微服务·rabbitmq
jianbiao14832 小时前
远程服务器下载llama模型
运维·服务器
武昌库里写JAVA2 小时前
Golang的消息中间件选型
java·开发语言·spring boot·学习·课程设计