Подтвердить что ты не робот

Как я могу скрыть PackageManager с помощью Robolectric

У моего Android-приложения есть простой способ скрыть намерение отобразить URL-адрес.

protected void launchBrowser(int id)
{
    Uri uri = Uri.parse( getString( id ) );
    Intent intent = new Intent( ACTION_VIEW, uri);

    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    if (activities.size() > 0)
    {
        startActivity(intent);
    }
    else
    {
        Toast.makeText(getApplicationContext(),
                       "ERROR - no application to display a web page",
                       Toast.LENGTH_SHORT).show();
    }
}

Я использую Robolectric для модульного тестирования, но у меня возникли проблемы с проверкой этого метода. В частности, getPackageManager() всегда возвращает null. Как я могу затенять PackageManager? Я попытался создать ShadowPackageManager и вызывать bindShadowClass, но ни один из моих кодов не будет выполнен - ​​getPackageManager() всегда возвращает null. Я также попытался применить тень контекста приложения и вернуть конкретный StubPackageManager, но получил те же результаты. Возможно, я слишком долго искал/смотрел - есть ли лучший способ unit test использовать этот метод?

4b9b3361

Ответ 1

Я использую Robolectric 2.3 для этого. Как отмечено в других ответах, getPackageManager() не возвращает значение null, но shadowApplication.setPackageManager больше не существует.

Поскольку вы не можете высмеивать PackageManager, вы не можете дать ему список Intents для решения. К счастью, подкласс Robolectric PackageManager, RobolectricPackageManager, может позволить вам добавить эти намерения без макета:

RobolectricPackageManager rpm = (RobolectricPackageManager)Robolectric.application.getPackageManager();
rpm.addResolveInfoForIntent(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), new ResolveInfo());

Ответ 2

По какой-то причине вам необходимо вручную установить теневой упаковщик вручную. Создайте собственный тестовый бегун (путем расширения RobolectricTestRunner) и переопределите метод setApplicationState:

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));
  }
}

Затем укажите в своих тестах, что вы хотите использовать свой собственный тестовый бегун:

@RunWith(MyTestRunner.class)
public class MyTest { ... }

Ответ 3

Я обновил до новейшего Robolectric (версия 2.1.1), и PackageManager больше не появляется null.

В приведенном ниже коде проверяется, что умывка браузера запущена (и настроена с помощью URL-адреса). Я не тестировал это на 1.x, но я думаю, что он работает и там:

@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" ) ) );
}

Примечание. Я вызываю начальную активность из фрагмента здесь.

Ответ 4

Просто добавьте в ответ aleph_null, вы можете использовать ShadowResolveInfo.newResolveInfo(), чтобы быстро создать макет ResolveInfo, готовый к использованию (я использую Robolectric 2.4).

RobolectricPackageManager rpm = (RobolectricPackageManager)Robolectric.application.getPackageManager();
rpm.addResolveInfoForIntent(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), ShadowResolveInfo.newResolveInfo(...));

Ответ 5

Вы можете установить ShadowPackageManager в отдельный метод (без расширения 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);
}

Примечание. Здесь я использовал mockito и высмеивал packagemanager для моего unittest вместо использования фактического PackageManager.

Ответ 6

Для Robolectric 3.1 вы можете

RobolectricPackageManager packageManager = RuntimeEnvironment.getRobolectricPackageManager();
// add necessary logic here