4

I have an android app. When the user clicks button A and intent is fired like this android-presudocode :)

//inside FirstActivity
@Override
public void onClick(View view) {
    startActivity(new Intent(this, AnotherActivity.class));
}

So if I'm not mistaken, the onResume method in AnotherActivity should be called, right?

I use ActivityInstrumentationTestCase2<FirstActivity> to test my activity but I'm unable to instantiate AnotherActivity.

So the question is, how can I test this: 'When a button is pressed, the correct activity is resumed and the correct extras are passed to the intent'.

fernandohur
  • 7,014
  • 11
  • 48
  • 86

4 Answers4

9

You can use the instrumentation to make an ActivityMonitor. This will monitor if a new activity has been started.

ActivityMonitor am = getInstrumentation().addMonitor(Activity3.class.getName(), null, true;

Then you want to use button.performClick() to "press the button". Finally, you check if the activity monitor has been hit.

am.waitForActivitywithTimeout(timeout);
assertEquals(1, am.getHits());

I haven't used ActivityInstrumentationTestCase2 in quite a while so I don't guarantee these steps are exactly right. In any case, I recommend that you take a look at Robolectric: a wonderful unit testing framework for Android that will change your life. It will help you overcome many situations that are difficult or impossible to test with any of the default instrumentation tests.

fernandohur
  • 7,014
  • 11
  • 48
  • 86
aleph_null
  • 5,766
  • 2
  • 24
  • 39
2

So after some time I want to post the solution that I use almost always. Initially I liked @aleph_null's solution but it turns out that it makes tests unbearably slow so this is what I use now:

First, I have this interface

/**
 * Simple interface to launch other activities.
 */
public interface ActivityLauncher {

    /**
     * Starts an activity with the Intent provided.
     * @param intent an intent
     */
    public void start(Context context, Intent intent);

    /**
     *
     * Returns the intent as set by {@link #start(android.content.Context,     android.content.Intent) start} or null if not yet
     * called.
     *
     * @return an intent or null
     */
    public Intent getIntent();
}

And I have two implementations for it:

/**
 * Default implementation of ActivityLauncher
 */
public class DefaultActivityLauncher implements ActivityLauncher{

    private Intent intent;

    public DefaultActivityLauncher(){}

    @Override
    public void start(Context context, Intent intent) {
        this.intent = intent;
        context.startActivity(intent);
    }

    @Override
    public Intent getIntent() {
        return intent;
    }
}

and

/**
 * Mock implementation of ActivityLauncher that simply sets the intent but does not actually starts
 * an activity.
 */
public class MockActivityLauncher implements ActivityLauncher {

    private Intent intent;

    @Override
    public void start(Context context, Intent intent) {
        this.intent = intent;
    }

    @Override
    public Intent getIntent() {
        return intent;
    }
}

Then I use a dependency injection framework like Dagger or similar like this:

 public class MyActivity {

    @Inject ActivityLauncher launcher;

    public void onCreate(Bundle bundle){

        // some code omitted for brevity
        findViewById(R.id.goToOtherActivityButton).setOnClick(new OnClickListener(){
           Intent intent = new Intent(getContext(), MyOtherActivity.class);
           launcher.start(getContext(), intent);
        });
    }

    public ActivityLauncher getLauncher(){
        return launcher;
    }
}

Testing is then as simple as checkIntentIsValid(activity.geLauncher().getIntent())

fernandohur
  • 7,014
  • 11
  • 48
  • 86
-1

This code might give you a good idea

If you are calling Activity1 --- > Activity2

You can send the UserName by this method

Intent intent = new Intent(getBaseContext(), Activity2.class);
intent.putExtra("UserName ", UserName );
startActivity(intent);

To retrive the Extra() in Activity2, you need this code

String UserName = (String) getIntent().getSerializableExtra("UserName ");

Hope this helps

Below Edit for Better Understanding

public class Activity2 extends Activity {
    private String UserName;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_2);
        UserName= (String) getIntent().getSerializableExtra("UserName");
        Log.i(Tag, "UserName: "+ UserName);
     }

    // you can call this method from click or where ever you want
    private void AnyMethod()
    {
           Intent intent = new Intent(getBaseContext(), Activity3.class);
           intent.putExtra("UserName ", UserName );
           startActivity(intent);
    }

 }
MDMalik
  • 3,951
  • 2
  • 25
  • 39
-1
@Override
public void onClick(View view) {
    startActivity(new Intent(this, AnotherActivity.class));
}

Your code is not correct in every time.

Example:

btn.setOnClickListener(new OnClickListener(
    @Override
    public void onClick(View view) {
        startActivity(new Intent(this, AnotherActivity.class));
    }
));

Please replace this = CurrentActivity.this

It looks like:

@Override
public void onClick(View view) {
    startActivity(new Intent(CurrentActivity.this, AnotherActivity.class));
}

Make ensure, your Manifest has this code:

<Activity name=".AnotherActivity">
</Activity>
Luc
  • 2,800
  • 2
  • 25
  • 46