EasyMock调用Mock对象方法时抛出NullPointerException问题求助
问题描述
测试类中尝试使用Mock对象:
@Mock private IDPool idPool; @Before private void before() { expect(idPool.getNextFree()).andReturn(TRACK_ID).anyTimes(); //line 63 }
运行测试时抛出NullPointerException:
java.lang.NullPointerException at com.mycompany.IDPool.getNextFree(IDPool.java:68) at com.mycompany.Test.before(Test.java:63)
异常出现在IDPool类的getNextFree方法中,该方法为final方法:
public final Integer getNextFree() { int nextFree; synchronized (this.usedIDs) { //line 68 //... } }
实际执行了生产代码而非Mock实现,需要解决Mock失效的问题。
解决方案
1. 修正@Before方法的访问修饰符
JUnit 4的@Before注解标记的方法必须是public,private方法不会被JUnit执行,导致Mock对象初始化逻辑无法运行。修改为:
@Before public void before() { // 初始化Mock及设置预期的代码 }
2. 确保Mock对象被正确初始化
使用@Mock注解后,需要让Mock框架完成对象初始化,否则idPool可能被错误创建为真实实例:
- 方式一:使用Mock框架的Runner
给测试类添加@RunWith(EasyMockRunner.class)(针对EasyMock):
@RunWith(EasyMockRunner.class) public class Test { @Mock private IDPool idPool; @Before public void before() { expect(idPool.getNextFree()).andReturn(TRACK_ID).anyTimes(); replay(idPool); // 调用replay激活Mock } }
- 方式二:手动初始化Mock
在@Before方法中调用MockAnnotations.initMocks(this):
public class Test { @Mock private IDPool idPool; @Before public void before() { MockAnnotations.initMocks(this); expect(idPool.getNextFree()).andReturn(TRACK_ID).anyTimes(); replay(idPool); } }
3. 处理final方法的Mock问题
getNextFree是final方法,EasyMock默认无法Mock final方法(final方法不能被代理类覆盖),可通过以下方式解决:
- 改用支持Mock final方法的框架:比如Mockito,配合
mockito-inline依赖即可实现。示例:
@ExtendWith(MockitoExtension.class) public class Test { @Mock private IDPool idPool; @BeforeEach public void setUp() { when(idPool.getNextFree()).thenReturn(TRACK_ID); } }
- 修改生产代码:如果允许,移除
getNextFree方法的final修饰符,让Mock框架可以生成代理类覆盖该方法。 - 使用EasyMock扩展库:旧版EasyMock可引入
easymock-class-extension依赖支持Mock final类和方法,但该库已停止维护,建议优先选择前两种方案。
注意:使用EasyMock时,设置完方法预期后必须调用replay(idPool),否则Mock对象仍会执行真实方法。
内容的提问来源于stack exchange,提问作者klarki
相关产品推荐
相关产品推荐

