You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:20:18