0

Ich habe eine Fragment-Klasse geschrieben, die an einem bestimmten Punkt überprüft, bevor Sie etwas ausführen isResumed(). Ich möchte Tests schreiben, die sicherstellen, dass dieser Code ausgeführt wird. In meinen Testfällen, die von ActivityUnitTestCase abgeleitet sind, scheint isResumed() jedoch immer false zurückzugeben. Gibt es eine Möglichkeit, in einem solchen Test true zurückgeben? Ich verwende die Fragmentklassen der Support-Bibliothek.Wie wird isResumed() wahr für ein Fragment in einem ActivityUnitTestCase zurückgegeben?

Hier ist ein Beispiel-Test, der ähnlichen Code verwendet, was meine realen Tests verwenden, und demonstriert das Problem. testIsResumed() schlägt immer fehl, weil isResumed() falsch ist, trotz onStart() und onResume() sowohl die Aktivität genannt zu haben, und das Fragment, und liberale Verwendung von waitForIdleSync():

public class FragmentIsResumedTest 
     extends ActivityUnitTestCase<FragmentIsResumedTest.TestActivity> { 
    public static class TestFragment 
      extends android.support.v4.app.Fragment { 
     @Override 
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
      return new LinearLayout(getContext()); 
     } 
    } 

    public static class TestActivity 
      extends android.support.v4.app.FragmentActivity { 
     @Override 
     protected void onCreate(@Nullable Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(new LinearLayout(this)); 
     } 
    } 

    public FragmentIsResumedTest() { 
     super(TestActivity.class); 
    } 

    public void testIsResumed() { 
     startActivity(
       new Intent(
         getInstrumentation().getTargetContext(), 
         TestActivity.class), 
       null, null); 
     getInstrumentation().waitForIdleSync(); 
     TestActivity activity = getActivity(); 
     TestFragment fragment = new TestFragment(); 
     fragment.onCreate(null); 
     getInstrumentation().callActivityOnStart(activity); 
     activity.getSupportFragmentManager().beginTransaction() 
       .add(android.R.id.content, fragment, "FragmentTag") 
       .commit(); 
     getInstrumentation().callActivityOnResume(activity); 
     fragment.onStart(); 
     fragment.onResume(); 
     getInstrumentation().waitForIdleSync(); 
     activity.getSupportFragmentManager().executePendingTransactions(); 
     getInstrumentation().waitForIdleSync(); 

     assertTrue(fragment.isResumed()); 
    } 
} 

Wie kann ich isResumed() gilt für meine Fragment in Unit-Tests machen, die von erweitern ActivityUnitTestCase?

Antwort

0

Was fehlt, ist, dass das Test-Setup in der Frage nie Activity.onPostResume() aufruft. In der Support-Bibliothek FragmentActivity, this is where the fragments are resumed from, durch den Aufruf dispatchResume() auf der FragmentManager. Wenn Sie einfach Fragment.onResume() manuell aufrufen, wird isResumed() nicht wahr zurückgegeben. Und aus irgendeinem Grund, Instrumentation.callActivityOnResume()never calls onPostResume(), und es gibt keine entsprechende callActivityOnPostResume().

Eine einfache Lösung ist onPostResume() Öffentlichkeit in TestActivity zu machen:

public static class TestActivity 
     extends android.support.v4.app.FragmentActivity { 
    @Override 
    public void onPostResume() { 
     super.onPostResume(); 
    } 

    /* ... */ 
} 

Und nennen Sie es irgendwann nach callActivityOnResume() im Testaufbau. Dies scheint sich um alle ausstehenden Fragmenttransaktionen zu kümmern, so dass executePendingTransactions() nicht mehr benötigt wird. Und der folgende Testcode funktioniert auch nach dem Entfernen aller Anrufe zu waitForIdleSync() für mich. Unter Verwendung von Mockito.spy() können wir sehen, dass alle Lebenszyklus-Methoden für das Fragment aufgerufen werden:

TestActivity activity = getActivity(); 
TestFragment fragment = spy(new TestFragment()); 
getInstrumentation().callActivityOnStart(activity); 
activity.getSupportFragmentManager().beginTransaction() 
     .add(android.R.id.content, fragment, "FragmentTag") 
     .commit(); 
getInstrumentation().callActivityOnResume(activity); 
activity.onPostResume(); 

assertTrue(fragment.isResumed()); 
InOrder inOrder = inOrder(fragment); 
inOrder.verify(fragment).onCreate(any(Bundle.class)); 
inOrder.verify(fragment).onViewCreated(any(View.class), any(Bundle.class)); 
inOrder.verify(fragment).onActivityCreated(any(Bundle.class)); 
inOrder.verify(fragment).onStart(); 
inOrder.verify(fragment).onResume();