33

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

    }

}
azizbekian
  • 60,783
  • 13
  • 169
  • 249
JoachimR
  • 5,150
  • 7
  • 45
  • 50

8 Answers8

61

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.

keineantwort
  • 873
  • 8
  • 15
8

Maybe a little late but this is also possible:

assertThat(activityRule.getActivityResult(), hasResultCode(Activity.RESULT_CANCELED));
head01
  • 571
  • 3
  • 12
5

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);
Prateek Sharma
  • 312
  • 3
  • 5
  • Way.2 works but you need to correct the way you launch the activity using: `ActivityScenario.launchActivityForResult(MyActivity.class);` instead – Noya Apr 05 '23 at 08:13
2

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

assertTrue(activityRule.scenario.result.resultCode == Activity.RESULT_CANCELED)
Jeff Padgett
  • 2,380
  • 22
  • 34
1

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

assertTrue(mTestRule.getActivity() == null);
SMR
  • 6,628
  • 2
  • 35
  • 56
1

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

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

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.

Community
  • 1
  • 1
kilian eller
  • 184
  • 2
  • 16
  • Thanks for your response. I guess I was not clear enough. My problem is that I don't have a second activity or a first activity. I only have one Activity. So I can use your solution only if I start a dummy first Activity just to be able to start my Activtiy that I want to test from there.. – JoachimR Mar 08 '16 at 10:19
  • so you have your runnable and wants to do something after it finished? – kilian eller Mar 08 '16 at 14:22
  • I want to make sure that my activity is closed after the fireEventThatResultsInTheActivityToFinishItself(); is called – JoachimR Mar 08 '16 at 14:26
0
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) }
k4dima
  • 6,070
  • 5
  • 41
  • 39