That's a tough one :). The problem here is that once the flow leaves your application (Google Account Picker is an external application), Espresso ends the test. Account Picker is an activity from the package com.google.android.gms
, thus external. Once it's started, your test is finished and you'll never be able to match anything in the dialog.
You have three possible solutions to make your tests feasible:
- Using classpath substitution on your app to fake the intents; or
- Fixing your app "testability"; or
- Using dependency injection, like Dagger
I'll show how to use classpath substitution. The technique is really simple: you should isolate your Intent creation in a separate class, say IntentsFactory
and, during tests, override that class.
Say your factory is in com.yourapp.factories.IntentsFactory
and it is something like this:
public class IntentsFactory {
public static Intent getAccountPickerIntent (Context context) {
return AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null);
}
}
You should create in your test app (say it is com.yourapp.tests
) a package with the same name and methods, but that returns a different Intent, a mocked/dummy one:
public class IntentsFactory {
public static Intent getAccountPickerIntent (Context context) {
return new Intent(context, MyDummyAccountPickerActivity.class);
}
}
Whenever your tests execute, they will use the "nearest" class in the classpath, that is, the IntentsFactory from your tests. Instead of returning an intent that send the flow to another app, the flow will go to an class of your project and Espresso won't end the tests.
The only caveat here is that you'll have to create the MyDummyAccountPickerActivity
which will return a result and a Bundle
similar to the one returned by the framework class. The activity should exists in your app's manifest and you'll have to instruct your emulator Dalvik runtime to allow classpath (check it out this this and this links) substitution with the following command line:
adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
adb shell stop installd
adb shell start installd
And execute your tests.
I had a similar problem to test the Camera and it's thoroughly discussed in Espresso forum
Intent googlePicker = AccountPicker.newChooseAccountIntent(null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null); startActivityForResult(googlePicker, Utils.PICK_ACCOUNT_REQUEST);
And logic for account selected.. Other life-cycle methods are not changed. – Nasopharynx