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