JUnit4+Mockito仅Mock类中单个静态方法的问题排查
测试静态方法methodA时Mock内部静态方法methodB的问题
待测试类
public class SomeClass { public static String methodA(String arg1) { return arg1 + methodB(); } public static String methodB() { OtherClass other = new OtherClass(); return OtherClass.doSomethingElse(); } }
问题场景
我需要测试methodA,但它依赖静态方法methodB,而methodB又依赖未初始化的OtherClass,所以尝试用Mockito的mockStatic来MockmethodB,测试代码如下:
MockedStatic<SomeClass> someClassInst = mockStatic(SomeClass.class); someClassInst.when(() -> SomeClass.methodB()).thenReturn("testStr"); someClassInst.when(() -> SomeClass.methodA(anyString())).thenCallRealMethod();
但调用String result = SomeClass.methodA("test")时始终抛出空指针异常,调试发现methodA执行return语句时触发异常,试过spy但问题更多,想问是否能用Mock实现需求。
当前依赖配置
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.5.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>3.7.0</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.7.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-engine</artifactId> <version>1.5.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.4.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.4.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>3.1.0</version> <scope>test</scope> </dependency>
问题原因及解决方案
原因分析
当使用mockStatic(SomeClass.class)时,默认会Mock该类的所有静态方法,此时即使你给methodA设置thenCallRealMethod,methodA内部直接调用的methodB并不会走Mockito的Mock代理,而是执行真实的methodB逻辑——这才是空指针的根源(真实methodB里的OtherClass或doSomethingElse()未被正确初始化)。
修正后的测试代码
不需要给methodA设置thenCallRealMethod,直接调用真实的methodA即可,同时确保methodB的Mock生效。另外,必须用try-with-resources管理MockedStatic,避免静态Mock污染其他测试:
import org.junit.jupiter.api.Test; import org.mockito.Mockito; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.times; class SomeClassTest { @Test void testMethodA() { try (MockedStatic<SomeClass> mockedSomeClass = Mockito.mockStatic(SomeClass.class)) { // Mock methodB的返回值 mockedSomeClass.when(SomeClass::methodB).thenReturn("testStr"); // 直接调用methodA,内部会使用Mock的methodB返回值 String result = SomeClass.methodA("test"); // 验证结果正确性 assertEquals("testtestStr", result); // 验证methodB被调用了一次 mockedSomeClass.verify(SomeClass::methodB, times(1)); } } }
依赖优化
你的依赖同时混合了JUnit 4和JUnit 5,容易引发版本冲突,建议统一使用JUnit 5,清理冗余依赖:
- 移除
junit:junit:4.12 - 移除
org.junit.vintage:junit-vintage-engine(如果不需要兼容JUnit 4测试) - 统一
junit-jupiter、junit-jupiter-engine的版本为一致的版本(比如都用5.5.2) - 确保
mockito-junit-jupiter版本与mockito-core、mockito-inline版本一致(比如都用3.7.0)
内容的提问来源于stack exchange,提问作者baggy696
相关产品推荐
相关产品推荐

