I'm trying to test my app behavior with Espresso-2.2
On main activity, when button pressed both service and another activity is being started:
public class MainActivity extends Activity {
public void onButtonClicked() {
startActivity(SecondActivity.getStartIntent());
startService(MyIntentService.getStartIntent());
}
}
I'm testing if intended components are being started:
public class MainActivityTest {
@Rule
public final IntentsTestRule<MainActivity> intentsRule = new IntentsTestRule<>(MainActivity.class, true);
@Test
public void shouldStartServiceOnButtonClicked() {
onView(withId(R.id.button)).perform(click());
intended(hasComponent(hasClassName(SecondActivity.class.getName())));
intended(hasComponent(hasClassName(MyIntentService.class.getName())));
}
}
but I'm getting error:
Caused by: junit.framework.AssertionFailedError: Wanted to match 1 intents. Actually matched 0 intents.
IntentMatcher: has component: has component with: class name: is "com.example.MyIntentService" package name: an instance of java.lang.String short class name: an instance of java.lang.String
Matched intents:[]
Recorded intents:
-Intent { cmp=com.example/.SecondActivity (has extras) } handling packages:[[com.example]], extras:[Bundle[...]])
at junit.framework.Assert.fail(Assert.java:50)
Start of SecondActivity is registered. Why start of my IntentService is not registered (I checked it is started)?
tl;dr it doesn't appear as if this is possible given the current espresso-intents provided functionality
I dug around in the source code since I'm trying to do something similar and this is what I found:
the 'intended' matcher works by looking at a list of recorded Intents. These are tracked by a callback that gets registered with the IntentMonitor instance when Intents.init() is called. The IntentMonitor instance is defined by the current Instrumentation. Any time the IntentMonitor's signalIntent() is called, the callback in Intents will be fired.
The problem lies in the fact that signalIntent() never actually gets called in the case where you call activity.startService() with an intent. This is because signalIntent() in the AndroidJunitRunner case only gets called by methods that are exposed on ExposedInstrumentationApi (which happen to correlate only to the various startActivity() methods). In order to use espresso-intents with startService() it would appear that an instrumentation hook for startService() would need to be available that would allow for calling signalIntent() on the IntentMonitor.
I don't have experience with adding custom Instrumentation to my test apks, but this is going to be my next avenue of investigation. I'll update my answer if I discover anything that works.
I could make an educated guess that the problem is that you are tying to assert that the IntentService
is created and running immediately after you call startService()
, while actually the startService()
is not synchronic call.
it does happens on the UI thread, but not imidiately. you can postpone the validation by a few mills and check then if the service started.