JoachimR
JoachimR

Reputation: 5258

Espresso how to test if Activity is finished?

I want to assert that my Acitivty that I am currently testing is finished when certain actions are performed. Unfortunately so far I am only to assert it by adding some sleep at the end of the test. Is there a better way ?

import android.content.Context;
import android.os.Build;
import android.support.test.rule.ActivityTestRule;
import android.test.suitebuilder.annotation.LargeTest;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import static org.junit.Assert.assertTrue;

@SuppressWarnings("unchecked")
@RunWith(JUnit4.class)
@LargeTest
public class MyActivityTest {

    Context context;

    @Rule
    public ActivityTestRule<MyActivity> activityRule
            = new ActivityTestRule(MyActivity.class, true, false);

    @Before
    public void setup() {
        super.setup();
        // ...
    }

    @Test
    public void finishAfterSomethingIsPerformed() throws Exception {

        activityRule.launchActivity(MyActivity.createIntent(context));

        doSomeTesting();

        activityRule.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                fireEventThatResultsInTheActivityToFinishItself();
            }
        });

        Thread.sleep(2000); // this is needed :(

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            assertTrue(activityRule.getActivity().isDestroyed());
        }

    }

}

Upvotes: 34

Views: 23242

Answers (8)

k4dima
k4dima

Reputation: 6251

val latch = CountDownLatch(1)
activityScenarioRule.scenario.onActivity {
        it.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) = latch.countDown()
        })
    }
latch.await(8, TimeUnit.SECONDS).let { Assert.assertTrue(it) }

Upvotes: 0

Prateek Sharma
Prateek Sharma

Reputation: 372

ActivityTestRule is deprecated now. So, my answer is based on ActivityScenario which is the new alternative for ActivityTestRule.

To test whether the current activity is finished(destroyed) or not. You can simply code like -

Way.1 ActivityScenario.launch(YourActivityName::class.java).use { activityScenario -> //Your test code

  assertTrue(activityScenario.state == Lifecycle.State.DESTROYED)
}
  • activityScenario.state tells the current state of the activity under test
  • Lifecycle.State.DESTROYED tells that the activity is destroyed

Way.2

ActivityScenario<MyActivity> scenario = ActivityScenario.launch(MyActivity.class);
   // Let's say MyActivity has a button that finishes itself.
   onView(withId(R.id.finish_button)).perform(click());
   assertThat(scenario.getResult().getResultCode()).isEqualTo(Activity.RESULT_OK);

Upvotes: 6

Jeff Padgett
Jeff Padgett

Reputation: 2529

If you haven't set a result in your activity, you can just use:

assertTrue(activityRule.scenario.result.resultCode == Activity.RESULT_CANCELED)

Upvotes: 2

Isidro Rodriguez
Isidro Rodriguez

Reputation: 475

I found a solution here https://stackoverflow.com/a/56491860/9402979, you can use

Espresso.pressBackUnconditionally()
assertTrue(activityRule.activity.isDestroyed)

Upvotes: 1

head01
head01

Reputation: 581

Maybe a little late but this is also possible:

assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));

Upvotes: 8

SMR
SMR

Reputation: 6736

Not sure if its a good practice but this worked for me:

assertTrue(mTestRule.getActivity() == null);

Upvotes: 1

keineantwort
keineantwort

Reputation: 883

In my case I can test for isFinishing():

assertTrue(activityTestRule.getActivity().isFinishing());

instead of:

    Thread.sleep(2000); // this is needed :(

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        assertTrue(activityRule.getActivity().isDestroyed());
    }

Another advantage of isFinishing() is, that you do not need the Version check.

Upvotes: 62

kilian eller
kilian eller

Reputation: 183

You can use StartActivityForResult sample below, more descriptions in links.

How to start Activity from FirstActivity:

Intent i = new Intent(this, SecondActivity.class);
startActivityForResult(i, 1);

That's how to finish your SecondActivity to go back to first (without sending result):

Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();

How to Raise Event when SecondActivity is finished (is wrote in FirstActivity):

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

   if (requestCode == 1) {

   }
}//onActivityResult

More you can find here: http://developer.android.com/training/basics/intents/result.html and there How to manage `startActivityForResult` on Android? there's also how you can send the data you want to get from SecondActivity.

Upvotes: 0

Related Questions