Spring Boot 中单元测试框架 Mockito 的正确使用
本文是对前段时间修复老项目单元测试的总结记录,在修复过程中,发现中文互联网中的不少文章对单元测试框架
Mockito
的使用说明基本不准确又或是AI生成,希望我这篇能够把这方面简单说透说对。
下文主要提及如下框架:
- Spring Boot
- Mockito
- PowerMock
Spring Boot编写简单单元测试
若只是希望使用Junit
编写比较简单的单元测试,建议直接引入Spring Boot
官方的测试依赖spring-boot-starter-test
,其内置了版本兼容的Junit
与Mockito
,开箱即用。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
如何Mock静态方法
上文提到 spring-boot-starter-test
已经引入 Mockito
,方便你对 Bean
进行Mock,但是你可能会发现其无法针对静态方法进行Mock。
此时,你可以检查下其引入的 Mockito
的具体版本,因为不同版本在Mock静态方法时的操作是不一样的。
主要可以分为Mockito
的版本是否小于v3.0.0。
Mockito
的版本小于v3.0.0
需要配合 PowerMock
使用以支持Mock静态方法!!!
- 其版本对应关系可以查看supported-versions,但请你先别急着引入该框架,继续往后看。
Mockito | PowerMock |
---|---|
2.8.9+ | 2.x |
2.8.0-2.8.9 | 1.7.x |
2.7.5 | 1.7.0RC4 |
2.4.0 | 1.7.0RC2 |
2.0.0-beta - 2.0.42-beta | 1.6.5-1.7.0RC |
1.10.8 - 1.10.x | 1.6.2 - 2.0 |
1.9.5-rc1 - 1.9.5 | 1.5.0 - 1.5.6 |
1.9.0-rc1 & 1.9.0 | 1.4.10 - 1.4.12 |
1.8.5 | 1.3.9 - 1.4.9 |
1.8.4 | 1.3.7 & 1.3.8 |
1.8.3 | 1.3.6 |
1.8.1 & 1.8.2 | 1.3.5 |
1.8 | 1.3 |
1.7 | 1.2.5 |
- 具体使用Demo可以查看Mocking Static Method。
我更加建议你将 Mockito
升级到大于v3.0.0的版本使用,其会更加简单稳定。
<!-- 仅需引入mockito-inline足矣,适用Junit4 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline<artifactId>
<version>4.11.0</version>
<scope>test</scope>
</dependency>
Mockito
的版本大于v3.0.0
直接展示下如何使用。
// 放在try中其Mock会自动关闭,建议都这么做,以免影响其他单元测试
try (MockedStatic<StaticExampleClass> staticExampleClassMock = Mockito.mockStatic(StaticExampleClass.class) ){
staticExampleClassMock.when(StaticExampleClass::execXxx).thenReturn("");
// 编写业务代码单元测试
}
其他一些问题
若你的Sping版本比较低,但是使用Mockito的版本比较高,比如上面我提到的4.11.0
,可能会出现这些错误信息:
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
Caused by: java.lang.IllegalStateException: Failed to load interface
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at
Caused by: org.mockito.exceptions.base.MockitoInitializationException:
It seems like you are running Mockito with an incomplete or inconsistent class path. Byte Buddy could not be loaded.
Byte Buddy is available on Maven Central as 'net.bytebuddy:byte-buddy' with the module name 'net.bytebuddy'.
For the inline mock maker, 'net.bytebuddy:byte-buddy-agent' with the module name 'net.bytebuddy.agent' is also required.
Normally, your IDE or build tool (such as Maven or Gradle) should take care of your class path completion but
at org.mockito.internal.exceptions.Reporter.missingByteBuddyDependency(Reporter.java:1131)
此时,请检查项目中实际依赖情况:
- 实际引入
mockito-core
的版本是否与mockito-inline
内置依赖版本一致? - 实际引入
byte-buddy
、byte-buddy-agent
、objenesis
的版本是否与mockito-core
内置依赖版本一致?
若不一致,请手动显式添加上述依赖,并令其版本为mockito-core
与mockito-inline
内置对应版本。
值得一提的是,Mockito
官方开发团队给出了上述第二个问题的发生原因:
Unfortunately Spring hardcodes a specific (older) version of ByteBuddy, which becomes problematic for evergreen projects such as Mockito. Therefore, explicitly specify version.
That's all~