I have a UI test which clicks a button, and then launch a new Activity in its onClickListener. The test checks whether expected intent is sent or not.
My problem is, I want to test whether expected intent is sent without actually launching the activity. Because I found that new activity initializes its state, and it makes subsequent tests flaky.
I know there are two Espresso Intents api, which are intended
and intending
, but both fail to meet my needs. intended
api actually launches the target activity, and intending
api doesn't launch the activity, but it calls onActivityResult
callback which I don't want either. Because I'm afraid that code inside onActivityResult
may cause another flakiness. Also intending
doesn't assert whether matching intent is sent, it just calls onActivityResult
callback when matching intent is found, which means I have to check whether onActivityResult
is called or not!
Is there any clean way to achieve what I want?
Espresso's
Intents
class is a concise and handy api, but when it doesn't meet your needs, there is an alternative. If you useAndroidJUnit4
test runner, you can getInstrumentaion
instance usingInstrumentationRegistry.getInstrumentation()
, and then you can addInstrumentation.ActivityMonitor
instance.The third parameter of
ActivityMonitor
constructor tells we want to block activity launching. Note that this approach has its limitation. In contrast to Espresso Intents' rich Matcher support, You can not set multiple condition forActivityMonitor
.You can find several samples in ApiDemos, especially in
ContactsSelectInstrumentation
class.If you want to test whether expected intent is sent without actually launching the activity you can do it by capturing the intent with an activityResult and then catching the activity :
This would catch any attempt of launching ActivityToBeOpened. If you want to be more specific you can also catch an intent with Extras:
Hope that helps.
Actually, you can block any intent to launch an external or your own activity but still use the rich Espresso Intents API:
You able to do that because Espresso Intents still records every Intent with IntentMonitor callback even if you block them. Look at the source code of Espresso Intents on how they do that.
If you use Robotium Solo framework you need to move your own
ActivityMonitor
before their one. Otherwise just skip the lines related to this.