So stellen Sie den Unit-Test in Android auf Fragment ein

Lesezeit: 14 Minuten

Benutzeravatar von Trev Sorbie
Trev Sorbie

Ich möchte eine Android-Fragment-Klasse komponententesten.

Kann ich einen Test mit AndroidTestCase einrichten oder muss ich ApplicationTestCase verwenden?

Gibt es nützliche Beispiele, wie diese beiden Testfälle verwendet werden können? Die Testbeispiele auf der Entwicklerseite sind minimal und scheinen sich nur auf das Testen von Aktivitäten zu konzentrieren.

Alles, was ich an anderer Stelle gefunden habe, sind Beispiele, bei denen die AndroidTestCase-Klasse erweitert wird, aber dann alles, was getestet wird, das Addieren von zwei Zahlen ist, oder wenn der Kontext verwendet wird, macht es einfach ein einfaches Get und testet, dass etwas nicht null ist!

So wie ich es verstehe, muss ein Fragment innerhalb einer Aktivität leben. Könnte ich also eine Scheinaktivität erstellen oder die Anwendung oder den Kontext dazu bringen, eine Aktivität bereitzustellen, in der ich mein Fragment testen kann?

Muss ich meine eigene Aktivität erstellen und dann ActivityUnitTestCase verwenden?

Benutzeravatar von Konstantin Loginov
Konstantin Loginow

Ich hatte mit der gleichen Frage zu kämpfen. Vor allem, da die meisten Codebeispiele bereits veraltet sind und Android Studio/SDKs verbessert werden, sind alte Antworten manchmal nicht mehr relevant.

Also, das Wichtigste zuerst: Sie müssen bestimmen, ob Sie verwenden möchten Instrumental oder einfach JUnit Prüfungen.

Der Unterschied zwischen ihnen wurde hier von SD wunderschön beschrieben; Kurz gesagt: JUnit-Tests sind leichter und erfordern keinen Emulator, um ausgeführt zu werden. Instrumental – geben Ihnen die Erfahrung, die dem tatsächlichen Gerät am nächsten kommt (Sensoren, GPS, Interaktion mit anderen Apps usw.). Lesen Sie auch mehr über Testen in Android.

1. JUnit-Test von Fragmenten

Nehmen wir an, Sie brauchen keine schweren Instrumentaltests und einfache Junit-Tests reichen aus. Ich verwende einen schönen Rahmen Roboterelektrik für diesen Zweck.

Fügen Sie gradle hinzu:

dependencies {
    .....
    testImplementation('junit:junit:4.12')
    testImplementation('org.robolectric:robolectric:3.0')
    testImplementation("org.mockito:mockito-core:1.10.8")
    testImplementation('com.squareup.assertj:assertj-android:1.0.0') {
    exclude module: 'support-annotations'
    }
    .....
}

Mockito, AsserJ sind optional, aber ich fand sie sehr nützlich, daher empfehle ich dringend, sie auch einzubeziehen.

Dann in Varianten bauen angeben Unit-Tests Als ein Artefakt testen:
Geben Sie hier die Bildbeschreibung ein

Jetzt ist es an der Zeit, ein paar echte Tests zu schreiben 🙂 Nehmen wir als Beispiel das Standard-Beispielprojekt “Blank Activity with Fragment”.

Ich habe einige Codezeilen hinzugefügt, um tatsächlich etwas zum Testen zu haben:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;

public class MainActivityFragment extends Fragment {

    private List<Cow> cows;
    public MainActivityFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {   
        cows = new ArrayList<>();
        cows.add(new Cow("Burka", 10));
        cows.add(new Cow("Zorka", 9));
        cows.add(new Cow("Kruzenshtern", 15));

        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    int calculateYoungCows(int maxAge) {
        if (cows == null) {
            throw new IllegalStateException("onCreateView hasn't been called");
        }

        if (getActivity() == null) {
            throw new IllegalStateException("Activity is null");
        }

        if (getView() == null) {
            throw new IllegalStateException("View is null");
        }

        int result = 0;
        for (Cow cow : cows) {
            if (cow.age <= maxAge) {
                result++;
            }
        }

        return result;
    }
}

Und Klasse Kuh:

public class Cow {
    public String name;
    public int age;

    public Cow(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Das Testset von Robolectic würde in etwa so aussehen:

import android.app.Application;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.test.ApplicationTestCase;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk=21)
public class MainActivityFragmentTest extends ApplicationTestCase<Application> {

    public MainActivityFragmentTest() {
        super(Application.class);
    }

    MainActivity mainActivity;
    MainActivityFragment mainActivityFragment;

    @Before
    public void setUp() {
        mainActivity = Robolectric.setupActivity(MainActivity.class);
        mainActivityFragment = new MainActivityFragment();
        startFragment(mainActivityFragment);
    }

    @Test
    public void testMainActivity() {
        Assert.assertNotNull(mainActivity);
    }

    @Test
    public void testCowsCounter() {
        assertThat(mainActivityFragment.calculateYoungCows(10)).isEqualTo(2);
        assertThat(mainActivityFragment.calculateYoungCows(99)).isEqualTo(3);
    }

    private void startFragment( Fragment fragment ) {
        FragmentManager fragmentManager = mainActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null );
        fragmentTransaction.commit();
    }
}

Dh wir erstellen Aktivität über Robolectric.setupActivity, neues Fragment im setUp() der Testklassen. Optional können Sie das Fragment sofort aus setUp() starten oder direkt aus dem Test heraus.

Achtung! Ich habe nicht ausgegeben zu viel Zeit darauf, aber es sieht so aus, als wäre es fast unmöglich, es mit Dagger zusammenzubinden (ich weiß nicht, ob es mit Dagger2 einfacher ist), da Sie keine benutzerdefinierte Testanwendung mit verspotteten Injektionen festlegen können.

2. Instrumentelle Prüfung von Fragmenten

Die Komplexität dieses Ansatzes hängt stark davon ab, ob Sie Dagger/Dependency Injection in der App verwenden, die Sie testen möchten.

Im Varianten bauen angeben Android-Instrumentaltests Als ein Artefakt testen:
Geben Sie hier die Bildbeschreibung ein

In Gradle füge ich diese Abhängigkeiten hinzu:

dependencies {
    .....
    androidTestCompile "com.google.dexmaker:dexmaker:1.1"
    androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.1"
    androidTestCompile 'com.squareup.assertj:assertj-android:1.0.0'
    androidTestCompile "org.mockito:mockito-core:1.10.8"
    }
    .....
}

(Auch hier sind so ziemlich alle optional, aber sie können Ihr Leben so viel einfacher machen)

– Wenn Sie keinen Dolch haben

Dies ist ein glücklicher Weg. Der Unterschied zu Robolectric von oben wäre nur in kleinen Details.

Vorstufe 1: Wenn Sie Mockito verwenden möchten, müssen Sie es mit diesem Hack aktivieren, damit es auf den Geräten und Emulatoren ausgeführt werden kann:

public class TestUtils {
    private static final String CACHE_DIRECTORY = "/data/data/" + BuildConfig.APPLICATION_ID + "/cache";
    public static final String DEXMAKER_CACHE_PROPERTY = "dexmaker.dexcache";

    public static void enableMockitoOnDevicesAndEmulators() {
        if (System.getProperty(DEXMAKER_CACHE_PROPERTY) == null || System.getProperty(DEXMAKER_CACHE_PROPERTY).isEmpty()) {
            File file = new File(CACHE_DIRECTORY);
            if (!file.exists()) {
                final boolean success = file.mkdirs();
                if (!success) {
                    fail("Unable to create cache directory required for Mockito");
                }
            }

            System.setProperty(DEXMAKER_CACHE_PROPERTY, file.getPath());
        }
    }
}

Das MainActivityFragment bleibt wie oben gleich. Das Testset würde also so aussehen:

package com.klogi.myapplication;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.test.ActivityInstrumentationTestCase2;

import junit.framework.Assert;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MainActivityFragmentTest extends ActivityInstrumentationTestCase2<MainActivity> {

    public MainActivityFragmentTest() {
        super(MainActivity.class);
    }

    MainActivity mainActivity;
    MainActivityFragment mainActivityFragment;

    @Override
    protected void setUp() throws Exception {
        TestUtils.enableMockitoOnDevicesAndEmulators();
        mainActivity = getActivity();
        mainActivityFragment = new MainActivityFragment();
    }

    public void testMainActivity() {
        Assert.assertNotNull(mainActivity);
    }

    public void testCowsCounter() {
        startFragment(mainActivityFragment);
        assertThat(mainActivityFragment.calculateYoungCows(10)).isEqualTo(2);
        assertThat(mainActivityFragment.calculateYoungCows(99)).isEqualTo(3);
    }

    private void startFragment( Fragment fragment ) {
        FragmentManager fragmentManager = mainActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                getActivity().getSupportFragmentManager().executePendingTransactions();
            }
        });

        getInstrumentation().waitForIdleSync();
    }

}

Wie Sie sehen können, ist die Test-Klasse eine Erweiterung von ActivityInstrumentationTestCase2 Klasse. Außerdem ist es sehr wichtig, darauf zu achten startFragment -Methode, die sich im Vergleich zum JUnit-Beispiel geändert hat: Standardmäßig werden keine Tests im UI-Thread ausgeführt, und wir müssen die Ausführung explizit aufrufen, wenn die Transaktionen von FragmentManager anstehen.

– Wenn Sie Dolch haben

Hier wird es ernst 🙂

Zuerst werden wir los ActivityInstrumentationTestCase2 zugunsten ActivityUnitTestCase Klasse als Basisklasse für alle Testklassen des Fragments.

Wie üblich ist es nicht so einfach und es gibt mehrere Fallstricke (dies ist eines von Beispielen). Also müssen wir unsere pimpen ActivityUnitTestCase zu ActivityUnitTestCaseOverride

Es ist ein bisschen zu lang, um es hier vollständig zu posten, also lade ich die vollständige Version davon hoch github;

public abstract class ActivityUnitTestCaseOverride<T extends Activity>
        extends ActivityUnitTestCase<T> {

    ........
    private Class<T> mActivityClass;

    private Context mActivityContext;
    private Application mApplication;
    private MockParent mMockParent;

    private boolean mAttached = false;
    private boolean mCreated = false;

    public ActivityUnitTestCaseOverride(Class<T> activityClass) {
        super(activityClass);
        mActivityClass = activityClass;
    }

    @Override
    public T getActivity() {
        return (T) super.getActivity();
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        // default value for target context, as a default
        mActivityContext = getInstrumentation().getTargetContext();
    }

    /**
     * Start the activity under test, in the same way as if it was started by
     * {@link android.content.Context#startActivity Context.startActivity()}, providing the
     * arguments it supplied.  When you use this method to start the activity, it will automatically
     * be stopped by {@link #tearDown}.
     * <p/>
     * <p>This method will call onCreate(), but if you wish to further exercise Activity life
     * cycle methods, you must call them yourself from your test case.
     * <p/>
     * <p><i>Do not call from your setUp() method.  You must call this method from each of your
     * test methods.</i>
     *
     * @param intent                       The Intent as if supplied to {@link android.content.Context#startActivity}.
     * @param savedInstanceState           The instance state, if you are simulating this part of the life
     *                                     cycle.  Typically null.
     * @param lastNonConfigurationInstance This Object will be available to the
     *                                     Activity if it calls {@link android.app.Activity#getLastNonConfigurationInstance()}.
     *                                     Typically null.
     * @return Returns the Activity that was created
     */
    protected T startActivity(Intent intent, Bundle savedInstanceState,
                              Object lastNonConfigurationInstance) {
        assertFalse("Activity already created", mCreated);

        if (!mAttached) {
            assertNotNull(mActivityClass);
            setActivity(null);
            T newActivity = null;
            try {
                IBinder token = null;
                if (mApplication == null) {
                    setApplication(new MockApplication());
                }
                ComponentName cn = new ComponentName(getInstrumentation().getTargetContext(), mActivityClass.getName());
                intent.setComponent(cn);
                ActivityInfo info = new ActivityInfo();
                CharSequence title = mActivityClass.getName();
                mMockParent = new MockParent();
                String id = null;

                newActivity = (T) getInstrumentation().newActivity(mActivityClass, mActivityContext,
                        token, mApplication, intent, info, title, mMockParent, id,
                        lastNonConfigurationInstance);
            } catch (Exception e) {
                assertNotNull(newActivity);
            }

            assertNotNull(newActivity);
            setActivity(newActivity);

            mAttached = true;
        }

        T result = getActivity();
        if (result != null) {
            getInstrumentation().callActivityOnCreate(getActivity(), savedInstanceState);
            mCreated = true;
        }
        return result;
    }

    protected Class<T> getActivityClass() {
        return mActivityClass;
    }

    @Override
    protected void tearDown() throws Exception {

        setActivity(null);

        // Scrub out members - protects against memory leaks in the case where someone
        // creates a non-static inner class (thus referencing the test case) and gives it to
        // someone else to hold onto
        scrubClass(ActivityInstrumentationTestCase.class);

        super.tearDown();
    }

    /**
     * Set the application for use during the test.  You must call this function before calling
     * {@link #startActivity}.  If your test does not call this method,
     *
     * @param application The Application object that will be injected into the Activity under test.
     */
    public void setApplication(Application application) {
        mApplication = application;
    }
    .......
}

Erstellen Sie einen abstrakten AbstractFragmentTest für alle Ihre Fragmenttests:

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

/**
 * Common base class for {@link Fragment} tests.
 */
public abstract class AbstractFragmentTest<TFragment extends Fragment, TActivity extends FragmentActivity> extends ActivityUnitTestCaseOverride<TActivity> {

    private TFragment fragment;
    protected MockInjectionRegistration mocks;

    protected AbstractFragmentTest(TFragment fragment, Class<TActivity> activityType) {
        super(activityType);
        this.fragment = parameterIsNotNull(fragment);
    }

    @Override
    protected void setActivity(Activity testActivity) {
        if (testActivity != null) {
            testActivity.setTheme(R.style.AppCompatTheme);
        }

        super.setActivity(testActivity);
    }

    /**
     * Get the {@link Fragment} under test.
     */
    protected TFragment getFragment() {
        return fragment;
    }

    protected void setUpActivityAndFragment() {
        createMockApplication();

        final Intent intent = new Intent(getInstrumentation().getTargetContext(),
                getActivityClass());
        startActivity(intent, null, null);
        startFragment(getFragment());

        getInstrumentation().callActivityOnStart(getActivity());
        getInstrumentation().callActivityOnResume(getActivity());
    }

    private void createMockApplication() {
        TestUtils.enableMockitoOnDevicesAndEmulators();

        mocks = new MockInjectionRegistration();
        TestApplication testApplication = new TestApplication(getInstrumentation().getTargetContext());
        testApplication.setModules(mocks);
        testApplication.onCreate();
        setApplication(testApplication);
    }

    private void startFragment(Fragment fragment) {
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();
    }
}

Hier gibt es mehrere wichtige Dinge.

1) Wir überschreiben setActivity() -Methode, um das AppCompact-Design auf die Aktivität festzulegen. Ohne das wird der Testanzug abstürzen.

2) setUpActivityAndFragment()-Methode:

ICH. erstellt Aktivität ( => getActivity() beginnt mit der Rückgabe eines Nicht-Null-Werts, in Tests und in der zu testenden App)

  1. onCreate() der aufgerufenen Aktivität;

  2. onStart() der aufgerufenen Aktivität;

  3. onResume() der aufgerufenen Aktivität;

II. Fragment an die Aktivität anhängen und starten

  1. onAttach() des aufgerufenen Fragments;

  2. onCreateView() des aufgerufenen Fragments;

  3. onStart() des aufgerufenen Fragments;

  4. onResume() des aufgerufenen Fragments;

3) createMockApplication()-Methode: Wie in der Non-Dagger-Version aktivieren wir in Pre-Step 1 das Mocking auf den Geräten und auf den Emulatoren.

Dann ersetzen wir die normale Anwendung mit ihren Injektionen durch unsere individuelle Testanwendung!

MockInjectionRegistration sieht aus wie:

....
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import de.greenrobot.event.EventBus;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Module(
        injects = {

                ....
                MainActivity.class,
                MyWorkFragment.class,
                HomeFragment.class,
                ProfileFragment.class,
                ....
        },
        addsTo = DelveMobileInjectionRegistration.class,
        overrides = true
)
public final class MockInjectionRegistration {

    .....
    public DataSource dataSource;
    public EventBus eventBus;
    public MixpanelAPI mixpanel;
    .....

    public MockInjectionRegistration() {
        .....
        dataSource = mock(DataSource.class);
        eventBus = mock(EventBus.class);
        mixpanel = mock(MixpanelAPI.class);
        MixpanelAPI.People mixpanelPeople = mock(MixpanelAPI.People.class);
        when(mixpanel.getPeople()).thenReturn(mixpanelPeople);
        .....
    }
...........
    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    DataSource provideDataSource() {
        Guard.valueIsNotNull(dataSource);
        return dataSource;
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    EventBus provideEventBus() {
        Guard.valueIsNotNull(eventBus);
        return eventBus;
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    MixpanelAPI provideMixpanelAPI() {
        Guard.valueIsNotNull(mixpanel);
        return mixpanel;
    }
.........
}

Dh statt echter Klassen stellen wir den Fragmenten ihre verspotteten Versionen zur Verfügung. (Die leicht nachvollziehbar sind, erlaubt es, Ergebnisse von Methodenaufrufen zu konfigurieren usw.).

Und die TestApplication ist nur Ihre benutzerdefinierte Erweiterung von Application, die das Setzen von Modulen unterstützen und den ObjectGraph initialisieren sollte.

Dies waren Vorstufen, um mit dem Schreiben der Tests zu beginnen 🙂
Jetzt der einfache Teil, die eigentlichen Tests:

public class SearchFragmentTest extends AbstractFragmentTest<SearchFragment, MainActivity> {
    
    public SearchFragmentTest() {
        super(new SearchFragment(), MainActivity.class);
    }

    @UiThreadTest
    public void testOnCreateView() throws Exception {
        setUpActivityAndFragment();

        SearchFragment searchFragment = getFragment();
        assertNotNull(searchFragment.adapter);
        assertNotNull(SearchFragment.getSearchAdapter());
        assertNotNull(SearchFragment.getSearchSignalLogger());
    }

    @UiThreadTest
    public void testOnPause() throws Exception {
        setUpActivityAndFragment();

        SearchFragment searchFragment = getFragment();
        assertTrue(Strings.isNullOrEmpty(SharedPreferencesTools.getString(getActivity(), SearchFragment.SEARCH_STATE_BUNDLE_ARGUMENT)));

        searchFragment.searchBoxRef.setCurrentConstraint("abs");
        searchFragment.onPause();

        assertEquals(searchFragment.searchBoxRef.getCurrentConstraint(), SharedPreferencesTools.getString(getActivity(), SearchFragment.SEARCH_STATE_BUNDLE_ARGUMENT));
    }

    @UiThreadTest
    public void testOnQueryTextChange() throws Exception {
        setUpActivityAndFragment();
        reset(mocks.eventBus);

        getFragment().onQueryTextChange("Donald");
        Thread.sleep(300);

        // Should be one cached, one uncached event
        verify(mocks.eventBus, times(2)).post(isA(SearchRequest.class));
        verify(mocks.eventBus).post(isA(SearchLoadingIndicatorEvent.class));
    }

    @UiThreadTest
    public void testOnQueryUpdateEventWithDifferentConstraint() throws Exception {
        setUpActivityAndFragment();

        reset(mocks.eventBus);

        getFragment().onEventMainThread(new SearchResponse(new ArrayList<>(), "Donald", false));

        verifyNoMoreInteractions(mocks.eventBus);
    }
    ....
}

Das ist es!
Jetzt haben Sie Instrumental/JUnit-Tests für Ihre Fragmente aktiviert.

Ich hoffe aufrichtig, dass dieser Beitrag jemandem hilft.

  • Das ist etwas wirklich Gutes. Vielen Dank, dass Sie mit uns geteilt haben!

    – Vulovic Vukasin

    6. Juli 2016 um 8:21 Uhr

  • Einfacher wäre es zu extrahieren calculateYoungCows() -Methode in eine separate Klasse und testen Sie diese einfach.

    – Andy Res

    19. August 2016 um 18:42 Uhr

Benutzeravatar von abhijit.mitkar
abhijit.mitkar

Angenommen, Sie haben eine FragmentActivity-Klasse mit dem Namen „MyFragmentActivity“, in der eine öffentliche Fragment-Klasse mit dem Namen „MyFragment“ mithilfe von FragmentTransaction hinzugefügt wird. Erstellen Sie einfach eine „JUnit Test Case“-Klasse, die ActivityInstrumentationTestCase2 in Ihrem Testprojekt erweitert. Rufen Sie dann einfach getActivity() auf und greifen Sie auf das MyFragment-Objekt und seine öffentlichen Member zu, um Testfälle zu schreiben.

Siehe das Code-Snippet unten:

// TARGET CLASS
public class MyFragmentActivity extends FragmentActivity {
    public MyFragment myFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        myFragment = new MyFragment();
        fragmentTransaction.add(R.id.mainFragmentContainer, myFragment);
        fragmentTransaction.commit();
    }
}

// TEST CLASS
public class MyFragmentActivityTest extends android.test.ActivityInstrumentationTestCase2<MyFragmentActivity> {
    MyFragmentActivity myFragmentActivity;
    MyFragment myFragment;

    public MyFragmentActivityTest() {
        super(MyFragmentActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        myFragmentActivity = (MyFragmentActivity) getActivity();
        myFragment = myFragmentActivity.myFragment;
    }

    public void testPreConditions() {
        assertNotNull(myFragmentActivity);
        assertNotNull(myFragment);
    }

    public void testAnythingFromMyFragment() {
        // access any public members of myFragment to test
    }
}

Ich hoffe das hilft. Akzeptieren Sie meine Antwort, wenn Sie dies nützlich finden. Vielen Dank.

  • Wie umgehen Sie TestRunner(16162): java.lang.RuntimeException: Aktivität kann nicht aufgelöst werden für: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.example/.test.MyFragmentActivityTest $MyFragmentActivity }

    – Mach

    19. Juli 2013 um 11:12 Uhr

  • @mach Kannst du bitte den vollständigen Stacktrace bereitstellen?

    – abhijit.mitkar

    23. Juli 2013 um 10:03 Uhr

  • Das obige Beispiel ist kein Komponententest, sondern ein Instrumentierungstest.

    – Muhammad Babar

    5. Juni 2015 um 11:04 Uhr

Ich bin mir ziemlich sicher, dass Sie tun können, was Sie sagen, eine Scheinaktivität erstellen und das Fragment von dort aus testen. Sie müssen nur die Kompatibilitätsbibliothek in das Hauptprojekt exportieren und können auf die Fragmente aus dem Testprojekt zugreifen. Ich werde ein Beispielprojekt erstellen und den Code hier testen und meine Antwort basierend auf dem, was ich herausfinde, aktualisieren.

Weitere Informationen zum Exportieren der Kompatibilitätsbibliothek finden Sie unter hier.

  • Können Sie hier etwas Code teilen, um Fragmente zu testen. Ich habe Probleme beim Unit-Testing von Fragmenten!

    – Muhammad Babar

    5. Juni 2015 um 11:16 Uhr


Benutzeravatar von Cristopher Cutas
Christoph Cutas

Hinzufügen zu @abhijit.mitkars Antwort.

In einem Szenario, in dem Ihr Fragment kein öffentliches Mitglied in der getesteten Aktivität ist.

protected void setUp() {
   mActivity = getActivity();
   mFragment = new TheTargetFragment();

   FragmentTransaction transaction = mActivity.getSupportFragmentManager().beginTransaction();
   transaction.add(R.id.fragment_container, mFragment, "FRAGMENT_TAG");
   transaction.commit();
}

Der Zweck des obigen Codes besteht darin, das Fragment durch ein neues Fragmentobjekt zu ersetzen, auf das wir Zugriff haben.

Mit dem folgenden Code können Sie auf die Mitglieder der Fragment-Benutzeroberfläche zugreifen.

TextView randomTextView= (TextView) mFragment.getView().findViewById(R.id.textViewRandom);

Abrufen der Benutzeroberfläche aus der Aktivität wird nicht geben Ihnen das erwartete Ergebnis.

TextView randomTextView= (TextView) mActivity.findViewById(R.id.textViewRandom);

Schließlich, wenn Sie einige Änderungen an der Benutzeroberfläche vornehmen möchten. Machen Sie es wie ein guter Android-Entwickler im Hauptthread.

mActivity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // set text view's value
    }
});

Notiz:
Vielleicht möchten Sie ihm jedes Mal ein Thread.sleep() geben, wenn ein Test endet. Um ein Abstürzen zu vermeiden, muss getInstrumentation().waitForIdleSync(); scheint nicht immer zu funktionieren.

ich benutzte ActivityInstrumentationTestCase2 seit ich Funktionstests mache.

1436020cookie-checkSo stellen Sie den Unit-Test in Android auf Fragment ein

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy