Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intent extras in Unit test Android Mockito

I am trying to verify that specific extras are added to Intent, but all the time I get null for the Intent in Unit test Android. I have the following class that need to be test:

public class TestClass extends SomeNotifier {
        private Intent mIntent = new Intent("testintent");

        public TestClassConstructor(Context context) {
            super(context);
        }

        @Override
        public void notifyChange() {
            mIntent.putExtra("Key one", 22);
            mIntent.putExtra("Key two", 23);
            mIntent.putExtra("Key three", 24);
            getContext().sendBroadcast(mIntent);
        }
    }

And the test is the following (I tried with mockIntent as well, but the result is the same, again the extras are null):

@RunWith(MockitoJUnitRunner.class)
public class TestClassTest {

  @Mock
  Context mMockContext;

  @Test
  public void sendBroadcastTest() {

  ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);

  TestClass testClassNotifier = new TestClass (mMockContext);
  testClassNotifier.notifyChange();
  verify(mMockContext).sendBroadcast(argument.capture());


 Intent intent = argument.getValue();
 //THE INTENT IS NULL
 Assert.assertTrue(intent.hasExtra("Key one"));

    }
}

Do you have any suggestion how should I make this test to work? Thanks in advance

like image 708
Mr.Robot Avatar asked Sep 28 '17 12:09

Mr.Robot


1 Answers

Intent and other Android runtime classes like Context are, by default, only available on physical Android handsets and emulators. For the local unit tests you are provided with a stubbed out version of the runtime where Intent etc. methods will return null by default. See this question for an explanation.

This means your current test is verifying against a stubbed out version of Intent which will return null for all of the method calls by default.

There are some ways around this - you can convert the test to an instrumented unit test which would mean you would have to run it on a real handset or emulator. Alternatively, you can wrap the Intent class with a class you control.

Perhaps the best solution is to use a framework like Robolectric. This will provide you with working test doubles (called shadows) of important Android classes like Intent for local unit tests that run in your IDE.

Once you have carefully installed Robolectric you would simply add the following to make your test work:

@RunWith(RobolectricTestrunner.class)
public class TestClassTest {

As an aside, please make sure you are using the correct dependencies for Mockito on Android:

testCompile 'org.mockito:mockito-core:2.8.9'
androidTestCompile 'org.mockito:mockito-android:2.8.9'
like image 76
David Rawson Avatar answered Nov 18 '22 03:11

David Rawson