如何修复java.lang.IllegalStateException: Failed to unwrap proxied object错误
问题分析与解决方案
错误根源
你遇到的java.lang.IllegalStateException: Failed to unwrap proxied object错误,核心原因是:
通过@Autowired注入的FirebaseService是Spring生成的代理对象(可能是CGLIB或JDK动态代理),而Mockito的spy()方法无法直接处理这种代理实例,导致无法正确剥离代理获取真实对象,进而引发Stub方法失败。
解决方案
方案1:使用Spring Boot Test的@SpyBean(推荐)
Spring Boot Test提供的@SpyBean注解可以直接创建Spring管理Bean的Spy,自动处理代理问题,无需手动调用Mockito的spy()。
修改测试代码:
@ExtendWith(SpringExtension.class) @SpringBootTest public class FirebaseServiceTest { // 用@SpyBean替代@Autowired+spy() @SpyBean private FirebaseService firebaseService; @Test public void whenGetAppIsEmpty_thenReturnFirebaseAppInstanceFromInitializeApp() throws IOException { // 直接Stub spyBean的方法 doReturn(FileInputStream.nullInputStream()) .when(firebaseService) .getServiceAccountFileInputStream(); // 执行测试逻辑 FirebaseApp app = firebaseService.initializeApp(); // 断言逻辑... } }
方案2:手动获取代理后的真实对象再Spy
如果坚持使用Mockito的spy(),需要先通过AopTestUtils.getTargetObject()获取Spring代理背后的真实对象,再创建Spy:
@ExtendWith(SpringExtension.class) @SpringBootTest public class FirebaseServiceTest { @Autowired private FirebaseService firebaseService; @Test public void whenGetAppIsEmpty_thenReturnFirebaseAppInstanceFromInitializeApp() throws IOException { // 获取代理后的真实对象 FirebaseService realService = AopTestUtils.getTargetObject(firebaseService); // 创建真实对象的Spy FirebaseService firebaseServiceSpy = spy(realService); doReturn(FileInputStream.nullInputStream()) .when(firebaseServiceSpy) .getServiceAccountFileInputStream(); // 执行测试逻辑 FirebaseApp app = firebaseServiceSpy.initializeApp(); // 断言逻辑... } }
注意:需要确保
spring-test依赖已引入,AopTestUtils属于该依赖。
方案3:脱离Spring容器手动实例化(适合简单测试)
如果你的测试不需要Spring上下文的其他依赖,可以直接手动实例化FirebaseService,避免代理问题:
// 不需要@SpringBootTest等Spring注解 public class FirebaseServiceTest { @Test public void whenGetAppIsEmpty_thenReturnFirebaseAppInstanceFromInitializeApp() throws IOException { // 手动创建真实实例 FirebaseService firebaseService = new FirebaseService(...); // 传入构造参数 // 创建Spy FirebaseService firebaseServiceSpy = spy(firebaseService); doReturn(FileInputStream.nullInputStream()) .when(firebaseServiceSpy) .getServiceAccountFileInputStream(); // 执行测试逻辑 FirebaseApp app = firebaseServiceSpy.initializeApp(); // 断言逻辑... } }
额外注意点
- 检查
getServiceAccountFileInputStream()方法是否为final:如果是final方法,Mockito无法Stub(对应错误提示的第2点),需要将该方法改为非final。 - 你使用的
doReturn(...).when(spy).method()是Spy对象Stub的正确语法(避免调用真实方法),这点本身没有问题,问题出在代理对象的处理上。
内容的提问来源于stack exchange,提问作者Israel Oluwole
相关产品推荐
相关产品推荐

