如何在不修改类结构的情况下,使用Mockito与JUnit5对新实例中的方法进行Mock?
如何在无法修改类结构时Mock嵌套实例化的SecondClass的secondMethod
你遇到的问题很典型——因为你的代码里ClasstToBeTested直接new FirstClass(),FirstClass又直接new SecondClass(),这种硬编码的对象实例化,普通的Mockito注解(比如@Spy)是没法生效的,因为你Spy的对象和目标类里实际使用的根本不是同一个实例。
要解决这个问题,我们需要用PowerMock来拦截构造函数的调用,把内部new出来的对象替换成我们的Mock实例。下面是具体的实现步骤:
1. 确认依赖(JUnit5版本)
你需要在项目中引入PowerMock的相关依赖,主要包括:
powermock-module-junit5:用于JUnit5的扩展支持powermock-api-mockito2:整合Mockito的API
2. 编写测试用例
下面是完整的测试代码,我会逐行解释关键逻辑:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit5.PowerMockExtension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; // 启用PowerMock的JUnit5扩展 @ExtendWith(PowerMockExtension.class) // 声明需要被PowerMock处理的类:所有内部有new操作的类都要在这里指定 @PrepareForTest({ClasstToBeTested.class, FirstClass.class}) public class ClasstToBeTestedTest { // Mock我们最终要控制的SecondClass @Mock private SecondClass mockSecondClass; @Test public void testMethodToBeTested() throws Exception { // 第一步:设定Mock对象的行为,让secondMethod返回我们想要的测试值 when(mockSecondClass.secondMethod()).thenReturn("Mocked Result"); // 第二步:用PowerMock拦截SecondClass的构造函数 // 这样每当代码里执行new SecondClass()时,都会返回我们预先Mock好的实例 PowerMockito.whenNew(SecondClass.class).withNoArguments().thenReturn(mockSecondClass); // 第三步:创建待测试类的实例 ClasstToBeTested testedInstance = new ClasstToBeTested(); // 第四步:执行测试并验证结果 String result = testedInstance.methodToBeTested(); assertEquals("Mocked Result", result); } }
关键逻辑说明
@PrepareForTest:必须指定所有包含new操作的类(这里是ClasstToBeTested和FirstClass),PowerMock需要修改这些类的字节码来拦截构造函数。PowerMockito.whenNew():这是核心方法,它会拦截指定类的构造调用,替换成我们的Mock对象。这样不管是FirstClass里的new SecondClass(),还是其他地方的调用,都会返回我们的Mock实例。- 为什么之前的
@Spy没用?因为你Spy的FirstClass是测试类里创建的,而ClasstToBeTested内部是自己new了一个全新的FirstClass实例,两者毫无关联,自然Mock不会生效。
内容的提问来源于stack exchange,提问作者Lolly
相关产品推荐
相关产品推荐

