Wie kann ich den PackageManager mit Robolectric schatten?

Meine Android-Anwendung hat eine einfache Methode, um eine Absicht abzuschließen, eine URL anzuzeigen.

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

Ich benutze Robolectric für Unit-Tests, aber ich habe Probleme bei der Überprüfung dieser Methode. Speziell wird getPackageManager() immer null zurückgegeben. Wie kann ich den PackageManager ? Ich habe versucht, einen ShadowPackageManager und bindShadowClass , aber keiner von meinem Code wird ausgeführt – getPackageManager() immer null . Ich habe auch versucht, den Anwendungskontext zu schatten und einen konkreten StubPackageManager , bekam aber die gleichen Ergebnisse. Vielleicht habe ich gesucht / starrte zu lange – gibt es einen besseren Weg zu Unit-Test diese Methode?

  • Android: WebView verbessern die Ladegeschwindigkeit der lokalen HTML-Dateien
  • Weicht SoftReference auf .cycy () auf Bitmap-Objekt auf
  • Broadcast Receiver und Ergebnisempfänger in Android
  • Griff Paging mit RxJava
  • ActionBar oder ActionBarSherlock - Ausblenden / Anzeigen der ActionBar
  • Android: Nachrichtenabsicht
  • Gibt es etwas Ähnliches wie Android XML-Zeichen in iOS?
  • Stapelüberlauf bei Verwendung von Retrofit rxjava concatWith
  • Tödliches Signal 11 (SIGSEGV) bei 0x00000000 (Code = 1) - PhoneGap
  • Android Studio - Debugging: Springe zum nächsten Break Point?
  • Mögliche nur bestimmte Zeilen Code nach Android OS Version laden?
  • Artikelliste anzeigen mit Slide - Like Gmail
  • 6 Solutions collect form web for “Wie kann ich den PackageManager mit Robolectric schatten?”

    Ich benutze Robolectric 2.3 dafür. Wie in anderen Antworten erwähnt, gibt getPackageManager() null nicht zurück, aber shadowApplication.setPackageManager existiert nicht mehr.

    Da können Sie nicht PackageManager , können Sie nicht geben es eine Liste der Intents zu lösen für. Glücklicherweise kann Robolectric's PackageManager Unterklasse, RobolectricPackageManager , Sie diese Absicht ohne einen Schein hinzufügen lassen:

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

    Aus irgendeinem Grund müssen Sie den Schattenpaketmanager manuell auf Ihre Anwendung setzen. Erstellen Sie einen benutzerdefinierten Test-Läufer (indem Sie RobolectricTestRunner erweitern) und überschreiben Sie die setApplicationState-Methode:

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

    Dann geben Sie in Ihren Tests an, dass Sie Ihren eigenen Testläufer verwenden möchten:

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

    Ich habe das neueste Robolectric (Version 2.1.1) aufgerüstet und der PackageManager kommt nicht mehr auf null .

    Der untenstehende Code verifiziert, dass eine Browserabsicht abgefeuert wird (und mit einer URL konfiguriert ist). Ich habe das nicht auf 1.x getestet, aber ich denke, es funktioniert auch dort:

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

    Anmerkung : Ich rufe die Startaktivität von einem Fragment hier an.

    Fügen Sie einfach auf die Antwort von aleph_null hinzu , können Sie ShadowResolveInfo.newResolveInfo() um schnell einen Spott zu erstellen. ResolveInfo bereit, verwendet zu werden (ich verwende Robolectric 2.4).

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

    Sie können den ShadowPackageManager in einer separaten Methode einstellen (ohne RobolectricTestRunner zu erweitern)

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

    Anmerkung : Hier habe ich mockito & verspottet den Paketmanager für meine unittest anstatt mit dem tatsächlichen PackageManager verwendet.

    Für Robolectric 3.1 können Sie

     RobolectricPackageManager packageManager = RuntimeEnvironment.getRobolectricPackageManager(); // add necessary logic here 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.