如何在JUnit测试中用EasyMock跳过createpage()方法调用?
createpage()方法的调用? 看起来你需要在测试headersection()方法时,跳过深层嵌套的createpage()调用——毕竟这个方法可能涉及实际的页面创建逻辑,不适合在单元测试中执行。结合你的代码结构(headersection()调用InformationHeader构造,构造触发makepage(),而makepage()是final方法并调用createpage()),我给你几个可行的解决方案:
方案1:使用Mockito Inline Mock Maker(推荐,无需额外框架)
从Mockito 3.4.0版本开始,通过启用inline mock maker,我们可以mock final方法和构造方法,完美适配你的场景:
配置Mockito支持final方法
在你的测试资源目录下,创建src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker文件,文件内容仅需一行:mock-maker-inline编写测试用例拦截构造并Stub方法
使用Mockito的mockConstructionAPI,我们可以拦截InformationHeader的实例创建,并对生成的mock对象的makepage()方法进行Stub,让它不执行原有逻辑(自然就不会调用createpage()了)。示例代码:import org.junit.jupiter.api.Test; import org.mockito.Mockito; import static org.mockito.Mockito.doNothing; class YourTestClass { @Test void testHeadersection() { // 拦截InformationHeader的构造过程,对每个生成的mock实例进行配置 try (var mockedConstruction = Mockito.mockConstruction(InformationHeader.class, (mock, context) -> { // Stub makepage()方法,让它什么都不做 doNothing().when(mock).makepage(); })) { // 调用你要测试的headersection方法 YourClassUnderTest testInstance = new YourClassUnderTest(); testInstance.headersection(yourChildObject); // 这里可以添加断言或验证逻辑,比如验证构造是否被触发 Mockito.verify(mockedConstruction.constructed().get(0)).makepage(); } } }
方案2:使用PowerMock(适合老版本Mockito)
如果你还在使用较老版本的Mockito,或者需要更强大的字节码操作能力,可以选择PowerMock:
添加PowerMock依赖
以Maven为例,根据你的JUnit版本添加对应依赖(下面是JUnit 4的示例,JUnit 5的依赖略有不同):<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency>编写测试用例
import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.mockito.Mockito.doNothing; @RunWith(PowerMockRunner.class) @PrepareForTest(InformationHeader.class) // 标记需要处理的类 class YourTestClass { @Test void testHeadersection() throws Exception { // 创建InformationHeader的mock实例 InformationHeader mockHeader = PowerMockito.mock(InformationHeader.class); // 拦截构造方法,返回mock实例 PowerMockito.whenNew(InformationHeader.class) .withAnyArguments() .thenReturn(mockHeader); // Stub makepage()方法,避免调用createpage() doNothing().when(mockHeader).makepage(); // 调用被测方法 YourClassUnderTest testInstance = new YourClassUnderTest(); testInstance.headersection(yourChildObject); // 验证构造方法是否被调用 PowerMockito.verifyNew(InformationHeader.class).withAnyArguments(); } }
方案3:代码重构(长期可维护性推荐)
如果允许修改生产代码,重构是最优雅的解决方案——让代码本身具备可测试性,而不是依赖测试框架的黑魔法:
我们可以把createpage()的逻辑抽离成独立的依赖(比如一个PageCreator接口),然后通过构造方法注入到InformationHeader中。这样测试时只需注入一个mock的PageCreator,就能轻松跳过实际的页面创建逻辑。
重构后的示例代码:
// 抽离页面创建逻辑为接口 public interface PageCreator { void createPage(); } // InformationHeader依赖PageCreator public class InformationHeader { private final PageCreator pageCreator; // 构造方法注入依赖 public InformationHeader(Param1 p1, Param2 p2, Param3 p3, Param4 p4, PageCreator pageCreator) { this.pageCreator = pageCreator; // 原有初始化代码 makepage(); } public final void makepage() { // 原有逻辑代码 pageCreator.createPage(); // 调用依赖的方法,替代原有的createpage() } }
测试时,你只需要创建一个mock的PageCreator,让它的createPage()方法什么都不做,再注入到InformationHeader中即可,完全不需要处理final方法或构造方法的mock问题。
内容的提问来源于stack exchange,提问作者Kinjal Rathod

