使用 PowerMockito 模拟 new A() 行为
使用 PowerMockito 模拟 new A()
行为
在 Java 测试中,当你想模拟 new A()
实例化的对象行为时,可以使用 PowerMockito。下面是一个完整的示例:
完整实现方案
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;import static org.junit.Assert.assertEquals;// 1. 使用PowerMockRunner
@RunWith(PowerMockRunner.class)
// 2. 准备要修改字节码的类
@PrepareForTest(YourClass.class) // 包含对new A()调用的类
public class YourClassTest {@Mockprivate A mockA; // Mock对象@Testpublic void testYourMethod() throws Exception {// 3. 设置mock对象的返回值Mockito.when(mockA.count()).thenReturn(15); // 模拟返回15// 4. 模拟new A()操作PowerMockito.whenNew(A.class).withNoArguments().thenReturn(mockA);// 5. 创建被测类实例YourClass yourClass = new YourClass();// 6. 执行测试int result = yourClass.yourMethod();// 7. 验证结果assertEquals(15, result);// 可选:验证方法是否被调用Mockito.verify(mockA).count();}
}class A {public int count() {return 0; // 实际实现}
}class YourClass {public int yourMethod() {A a = new A(); // 需要被模拟的实例化return a.count();}
}
Maven 依赖配置
<dependencies><!-- JUnit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!-- Mockito Core --><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.3.1</version><scope>test</scope></dependency><!-- PowerMock --><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>
</dependencies>
关键步骤解析
测试类配置:
@RunWith(PowerMockRunner.class)
:使用PowerMock运行器@PrepareForTest(YourClass.class)
:指定需要修改字节码的类
模拟构造函数:
PowerMockito.whenNew(A.class) // 拦截对A类的实例化.withNoArguments() // 使用无参构造函数.thenReturn(mockA); // 返回模拟对象
设置方法返回值:
Mockito.when(mockA.count()) // 当调用count()方法时.thenReturn(15); // 返回指定值
实际效果说明
当 yourMethod()
中的 new A()
执行时:
- PowerMock 会拦截构造函数调用
- 返回预先创建的
mockA
实例 - 调用
count()
方法时返回预设值 (15)
这样既不需要修改被测试类的代码,也能完全控制新创建对象的行为。
注意事项
- 测试效率:PowerMock 修改字节码,会使测试执行变慢
- 兼容性:确保 PowerMock 版本与 Mockito/JUnit 版本兼容
- 替代方案:优先考虑重构代码使用依赖注入
- 范围限制:只能模拟
new
表达式直接出现的类
对于简单场景,推荐优先重构代码使用依赖注入。但当处理遗留代码或第三方库时,PowerMock 提供的这种能力非常有用。