Robolectric中的getSystemService返回上下文为null的对象



在我的活动的onCreate中,我有:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

当用Robolectric测试活动时,我用创建它

ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
MainActivity activity = controller.attach().create().get();

然后创建AudioManager,但使用mContext = null,这在对其调用registerMediaButtonEventReceiver时导致NullPointerException,因为该框架方法在内部使用上下文。

有什么方法可以确保AudioManager是用一个工作的Context创建的吗?

我对此进行了一些尝试,实际上我认为目前的答案是,没有办法。

现在,如果目的只是在创建活动时避免NPE,那么您可能可以通过在测试中这样做来避开Mocking the AudioManager,对于Robolectric版本<3:

    AudioManager mockManager= Mockito.mock(AudioManager.class);
    Application application = (Application) Robolectric.getShadowApplication().getApplicationContext();
    ShadowContextImpl shadowContext = (ShadowContextImpl) Robolectric.shadowOf(application.getBaseContext());
    shadowContext.setSystemService(Context.AUDIO_SERVICE, mockManager);

另一种变体可能是创建自己的ShadowAudioManager,它可以处理registerMediaButtonEventReceiver,也可以使用正确的上下文进行初始化,因为当前的版本没有这样做,但我实际上还没有尝试过。

为了避免类似的NPE崩溃,我添加了

 @Config(emulateSdk = 18, shadows = {ShadowAudioManager.class}) 

在包含测试的类中!

使用Robolectric 3+使用:

AudioManager mockManager= Mockito.mock(AudioManager.class);
Application application = (Application) Robolectric.getShadowApplication().getApplicationContext();
ShadowContextImpl shadowContext = (ShadowContextImpl) Shadows.shadowOf(application.getBaseContext());
shadowContext.setSystemService(Context.AUDIO_SERVICE, mockManager);

当调用getActiveNetworkInfo()时,我必须模拟ConnectivityManager以返回一个空的NetworkInfo对象,使用Roboelectric 4.4可以做到这一点:

val context: Context = ApplicationProvider.getApplicationContext()
val spiedConnManager = spy(context.getSystemService(Context.CONNECTIVITY_SERVICE) 
                           as ConnectivityManager)
//set the service to return what you want, 
//in my case I set the connectivity manager to return null for activeNetworkInfo
doReturn(null).`when`(spiedConnManager).activeNetworkInfo
val shadowApp: ShadowApplication = shadowOf(context as Application)
//setSystemService is deprecated but I did not found a replacement yet
shadowApp.setSystemService(Context.CONNECTIVITY_SERVICE, spiedConnManager)
//perform your asserts HERE

您可以对任何需要的系统服务使用相同的方法

最新更新