本文主要是介绍【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失败,但是线上能执行成功的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!