Creating intent in test: “Method putExtra in android.content.Intent not mocked”

心已入冬 提交于 2020-05-30 07:19:22

问题


I'm trying to unit test a broadcast receiver which listens for "com.android.music.metachanged" intents using JUnit4 and Mockito.

The broadcast receiver starts a service when it receives an intent. I want to assert that the service is started. I also want to assert that the string extra "artist" of the received intent is the same as the one of the sent intent.

This is what I have so far...

@RunWith(PowerMockRunner.class)
public class MusicBroadcastReceiverUnitTest {
    private MusicBroadcastReceiver mReceiver;

    @Mock
    private Context mContext;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mReceiver = new MusicBroadcastReceiver();
    }

    @Test
    public void testStartMusicRegistrationService() {
        Intent intent = new Intent("com.android.music.metachanged");
        intent.putExtra("artist", "SampleArtist");

        mReceiver.onReceive(mContext, intent);
        assertNull(mReceiver.getResultData());

        ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(1)).startService(argument.capture());

        Intent receivedIntent = argument.getValue();
        assertEquals("SampleArtist", receivedIntent.getStringExtra("artist"));
    }
}

But this fires a java.lang.RuntimeException: Method putExtra in android.content.Intent not mocked.

I checked this out, but I think the OP had a different problem, since they don't send out an intent from inside the test body.


回答1:


All right, I took a look at Method of ContentValues is not mocked as suggested by @Jeff Bowman. Sadly, that question doesn't provide any code, so I hope this will be useful for somebody...

@RunWith(PowerMockRunner.class)
public class MusicBroadcastReceiverUnitTest {
    private MusicBroadcastReceiver mReceiver;

    @Mock
    private Context mContext;

    @Mock
    private Intent androidIntent;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mReceiver = new MusicBroadcastReceiver();
    }

    @Test
    public void testStartMusicRegistrationService() {
        try {
        PowerMockito.whenNew(Intent.class)
               .withArguments(String.class).thenReturn(androidIntent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        when(androidIntent.getAction())
          .thenReturn("com.android.music.metachanged");
        when(androidIntent.getStringExtra("artist"))
          .thenReturn("SampleArtist");

        mReceiver.onReceive(mContext, intent);

        ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(1)).startService(argument.capture());

        Intent receivedIntent = argument.getValue();
        assertEquals("SampleArtist", receivedIntent.getStringExtra("artist"));
    }
}

So yeah, I rather mocked "getStringExtra" than "putExtra". But it worked for me.




回答2:


If you're like me and saw this error when running unit tests, but you didn't care about testing the putExtra portion of the code, you can use:

android {
    // ...
    testOptions {
        unitTests.returnDefaultValues = true
    }
}

in your app's build.gradle file.



来源:https://stackoverflow.com/questions/41172775/creating-intent-in-test-method-putextra-in-android-content-intent-not-mocked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!