JUnit4+Mockito下Jersey项目Mock注入失败,如何Mock静态类方法?
问题分析与解决方案
你的代码存在三个核心问题:
- 静态方法无法被普通Mock拦截:ClassA的
method1直接调用ClassB.getInstance()这个静态方法获取实例,你用@Mock创建的classBInst和这个静态方法返回的实例完全无关,@InjectMocks也没法替换这种静态获取的对象——因为ClassA根本没有持有ClassB的成员变量,而是每次调用都自己获取。 - Mock的方法不匹配:你在
setup里Mock的是isClientEnabled()方法,但实际method1调用的是doSomething(),两者完全不对应。 - Mockito注解未初始化:你的测试类没有添加
@RunWith(MockitoJUnitRunner.class),也没在setup里调用MockitoAnnotations.initMocks(this),导致@Mock和@InjectMocks注解根本没生效,创建的mock对象是无效的。
正确解决方式分两种场景:
场景1:允许修改ClassA代码(推荐,符合依赖注入原则)
重构ClassA,将ClassB的实例通过构造方法注入,而不是直接调用静态方法:
public class ClassA { private final ClassB classBInst; // 构造注入,方便测试时传入mock对象 public ClassA(ClassB classBInst) { this.classBInst = classBInst; } public String method1() { return classBInst.doSomething(); } }
对应的测试类(JUnit4+Mockito):
import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) // 必须添加这个注解,让Mockito处理注解 public class TestClassA { @Mock private ClassB classBInst; private ClassA classAInst; @Before public void setup() { // 手动注入mock对象 classAInst = new ClassA(classBInst); // Mock目标方法doSomething的返回值 when(classBInst.doSomething()).thenReturn("ReturnStr"); } @Test public void testMethod1() { String result = classAInst.method1(); assertEquals("ReturnStr", result); } }
场景2:不能修改ClassA代码(用Mockito静态Mock)
如果无法改动ClassA,需要使用Mockito的静态Mock功能(要求Mockito版本3.4.0及以上),直接MockClassB.getInstance()静态方法,让它返回你创建的mock实例:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class TestClassA { @Mock private ClassB classBInst; @Test public void testMethod1() { // 静态Mock ClassB类,指定在try块内生效 try (var mockedStatic = mockStatic(ClassB.class)) { // 让getInstance()返回我们的mock实例 mockedStatic.when(ClassB::getInstance).thenReturn(classBInst); // Mock doSomething方法的返回值 when(classBInst.doSomething()).thenReturn("ReturnStr"); String result = new ClassA().method1(); assertEquals("ReturnStr", result); } } }
内容的提问来源于stack exchange,提问作者baggy696
相关产品推荐
相关产品推荐

