使用 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 {
@Mock
private A mockA; // Mock对象
@Test
public 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 提供的这种能力非常有用。