升级Pushwoosh后测试出现ExceptionInInitializerError问题求助
嘿,我之前也踩过Pushwoosh和Robolectric兼容的坑,这个ExceptionInInitializerError大概率是GeofenceReceiver的静态初始化逻辑在Robolectric的模拟环境里跑不通——毕竟Robolectric没法完全模拟所有Android系统服务,而Pushwoosh的地理围栏模块可能依赖了一些真实系统才有的类或者服务。
先把你遇到的错误栈贴出来方便定位:
java.lang.ExceptionInInitializerError at com.pushwoosh.location.geofencer.GeofenceReceiver.<init>(Unknown Source) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Nat...
给你几个可以尝试的解决方向,按优先级来:
对齐Robolectric和目标SDK版本:Robolectric对不同SDK版本的模拟差异很大,确保你在测试类的
@Config注解里指定的SDK版本和项目的targetSdkVersion完全一致。比如:@RunWith(RobolectricTestRunner.class) @Config(sdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) // 替换成你的targetSdk版本 public class YourTestClass { // ...测试代码 }Mock或Shadow掉GeofenceReceiver:如果你的测试根本不需要用到地理围栏功能,直接用Mockito或者Robolectric的Shadow类来绕过这个Receiver的初始化。比如用Mockito在测试前拦截Receiver的实例化:
@Before public void setUp() { // 禁止GeofenceReceiver被实例化 Mockito.mockStatic(GeofenceReceiver.class); }或者自定义Shadow类覆盖有问题的初始化逻辑:
@Implements(GeofenceReceiver.class) public class ShadowGeofenceReceiver { @Implementation public void __constructor__() { // 空实现,跳过原构造里的静态初始化 } }然后在
@Config里指定这个Shadow类。禁用Pushwoosh的自动初始化:有些版本的Pushwoosh会在App启动时自动初始化地理围栏模块,你可以在测试的
@Before方法里手动禁用这个自动初始化,比如调用Pushwoosh提供的测试工具类(如果有的话):@Before public void setUp() { Pushwoosh.setApplicationContext(RuntimeEnvironment.application); Pushwoosh.getInstance().disableGeofence(); }排除Pushwoosh的地理围栏模块:如果你的项目本身就没用到地理围栏功能,干脆在build.gradle里把这个模块排除掉,从根源上避免依赖冲突:
implementation 'com.pushwoosh:pushwoosh:X.X.X' { // 替换成你的Pushwoosh版本 exclude group: 'com.pushwoosh', module: 'pushwoosh-geofence' }检查自定义测试运行器的配置:你提到修改了自定义测试运行器,可能是运行器没有正确加载AndroidManifest里的Receiver配置,导致Robolectric无法识别这个组件。可以在
@Config里明确指定manifest路径:@Config(manifest = "src/main/AndroidManifest.xml", sdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
试试这些方法,应该能解决这个初始化错误。
内容的提问来源于stack exchange,提问作者Arkhipov Pavel

