How can I shadow the PackageManager with Robolectric

后端 未结 6 812
有刺的猬
有刺的猬 2020-12-15 22:16

My Android application has a simple method to fire off an intent to display a URL.

protected void launchBrowser(int id)
{
    Uri uri = Uri.parse( getStrin         


        
相关标签:
6条回答
  • 2020-12-15 23:02

    I'm using Robolectric 2.3 for this. As noted in other answers, getPackageManager() does not return null, but shadowApplication.setPackageManager no longer exists.

    Since you can't mock PackageManager, you can't give it a list of Intents to resolve for. Fortunately, Robolectric's PackageManager subclass, RobolectricPackageManager, can let you add these intents without a mock:

    RobolectricPackageManager rpm = (RobolectricPackageManager)Robolectric.application.getPackageManager();
    rpm.addResolveInfoForIntent(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), new ResolveInfo());
    
    0 讨论(0)
  • 2020-12-15 23:02

    For some reason you need to set the shadow packagemanager manually on your application. Create a custom test runner (by extending RobolectricTestRunner) and override the setApplicationState method:

    public class MyTestRunner extends RobolectricTestRunner {   
      @Override
      public void setupApplicationstate(RobolectricConfig robolectricConfig) {
         super.setupApplicationState(robolectricConfig);
         ShadowApplication shadowApplication = shadowOf(Robolectric.application);
         shadowApplication.setPackageName(robolectricConfig.getPackageName());
         shadowApplication.setPackageManager(new RobolectricPackageManager(Robolectric.application, robolectricConfig));
      }
    }
    

    Then specify in your tests that you want to use your own test runner:

    @RunWith(MyTestRunner.class)
    public class MyTest { ... }
    
    0 讨论(0)
  • 2020-12-15 23:04

    For Robolectric 3.1 you can

    RobolectricPackageManager packageManager = RuntimeEnvironment.getRobolectricPackageManager();
    // add necessary logic here
    
    0 讨论(0)
  • 2020-12-15 23:07

    Just add on to aleph_null's answer, you can use ShadowResolveInfo.newResolveInfo() to quickly create a mock ResolveInfo ready to be used (I'm using Robolectric 2.4).

    RobolectricPackageManager rpm = (RobolectricPackageManager)Robolectric.application.getPackageManager();
    rpm.addResolveInfoForIntent(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), ShadowResolveInfo.newResolveInfo(...));
    
    0 讨论(0)
  • 2020-12-15 23:15

    You can set the ShadowPackageManager in a separate method (without extending RobolectricTestRunner)

    private void setupPackageManager() {
        ShadowApplication shadowApplication = shadowOf(Robolectric.application);
        shadowApplication.setPackageManager(mockPackageManager);
        List<ResolveInfo> activities = new ArrayList<ResolveInfo>();
        activities.add(resolveInfo("com.test.package.Class1"));
        activities.add(resolveInfo("com.test.package.Class2"));
        when(mockPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(activities);
    }
    

    Note : Here, i have used mockito & mocked the packagemanager for my unittest instead of using the actual PackageManager.

    0 讨论(0)
  • 2020-12-15 23:16

    I upgraded to the latest Robolectric (version 2.1.1) and the PackageManager doesn't come up null anymore.

    The code below verifies that a browser intent is fired (and configured with a url). I haven't tested this on 1.x, but I think it works there too:

    @Test
    public void recipeTitleShouldOpenBrowserOnClick() throws Exception
    {
        title.performClick();
        ShadowActivity shadowActivity = shadowOf( detailFragment.getActivity() );
        ShadowActivity.IntentForResult intent = shadowActivity.peekNextStartedActivityForResult();
    
        // or
        // ShadowActivity.IntentForResult intent = shadowActivity.getNextStartedActivityForResult();
    
        assertThat( intent.intent,
                    equalTo( createBrowserIntentWithURL( "url" ) ) );
    }
    

    Note: I'm invoking start activity from a fragment here.

    0 讨论(0)
提交回复
热议问题