Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Robolectric to test starting of a service with intent extras?

Can I use Robolectric to test that an Activity starts a Service with a specific Bundle passed with the Intent? Answer: Yes!

I want to write a Robolectric-based test that tests that my MainActivity starts MyService with a specific number passed in intent extras:

in "MainActivity.java" I have the method

public void startMyService() {
  Intent i = new Intent(this, MyService.class);
  Bundle intentExtras = new Bundle();
  // TODO: Put magic number in the bundle
  i.putExtras(intentExtras);
  startService(i);
}

and this is my test case "MainActivityTest.java":

import ...

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class MainActivityTest extends TestCase {
  @Override
  protected void setUp() throws Exception {
    super.setUp();
  }

  @Override
  protected void tearDown() throws Exception {
    super.tearDown();
  }

  @Test
  public void testShallPassMagicNumberToMyService() {
    MainActivity activityUnderTest = Robolectric.setupActivity(MainActivity.class);
    activityUnderTest.startMyService();

    Intent receivedIntent = shadowOf(activityUnderTest).getNextStartedService();

    assertNotNull("No intents received by test case!", receivedIntent);

    Bundle intentExtras = receivedIntent.getExtras();
    assertNotNull("No intent extras!", intentExtras);

    long receivedMagicNumber = intentExtras.
            getLong(MyService.INTENT_ARGUMENT_MAGIC_NUMBER);

    assertFalse("Magic number is not included with the intent extras!",
            (receivedMagicNumber == 0L));  // Zero is default if no 'long' was put in the extras
  }
}

So, my question is: Can I use Robolectric for this purpose?

I think I figured this out, see answer below...

The test case does not work because it reports "No intent extras!". Using the debugger I've noticed that Intent.putExtras() has no effect in the Robolectric environment. The i.mExtras (Intent.mExtras) property is correctly set to a Bundle reference when I run the app on my device. When I run the test case it is null. I suppose that this hints that the answer to my question is "no", so should I give up on this test case or is there any way to accomplish this test?

Edit: Corrected the example startMyActivity() method to reflect what I actually had a problem with: It seems the Intent.mExtras property does not get populated unless there are some contents in the Bundle(?). This differs from the live Android environment which is what I analyzed with the debugger.

like image 512
jokki Avatar asked Nov 09 '22 15:11

jokki


1 Answers

I was not entirely accurate in how I presented my example code! I've updated the example to show the code I was having trouble with.

Turns out there's a difference in how an Intent is managed in the Robolectric environment compared to the real Android environment. With Robolectric Intent.mExtras does not get populated by Intent.putExtras() unless there's actually some content in the Bundle added to the Intent as extras.

like image 58
jokki Avatar answered Nov 14 '22 22:11

jokki