Tmarsh2
Tmarsh2

Reputation: 417

Mockito ClassNotFoundException for Android classes

I am trying to do some unit tests, on fragments and activities that use SharedPrefrences, amongst other Android related classes. However, I seem to always get a ClassNotFound Exception when I try to mock these like the below:

ClassNotFoundException: android.content.Context

Here is an example:

My 'TimerFragment' contains a 'MyNotificationManager' class.

@RunWith(MockitoJUnitRunner.class)
public class TimerFragmentUnitTest {

    @Mock
    TimerFragmentView view;
    @Mock
    MyNotificationManger notificationManger;


    private TimerFragmentPresenter presenter;

    @Before
    public void setUp(){
        presenter = new TimerFragmentPresenter(notificationManger);
        presenter.bindView(view);
    }

    @Test
    public void shouldSendNotification() throws Exception{
        //Given
        doNothing().when(view).setStopEnabled(false);
        doNothing().when(view).setStopEnabled(true);
        //When
        presenter.setMinutesAndSeconds(2000);
        TimeUnit.MILLISECONDS.sleep(3000);
        //Then
        verify(notificationManger,times(1)).sendTimerFinishNotification();


    }

}

In this example, I am getting a ClassNotFoundException: android.content.Context error, because MyNotificationManager has a Context object in it.

Any advice would be appreciated.

Thanks.

Here is an implementation of the MyNotificationTimer

    public class MyNotificationManger {

        private static final String EXTRA_NOTIFICATION_TIMER = "notification_timer";
        private static final int TIMER_NOTIFICATION_ID = 1;
        private final Context _context;

        public MyNotificationManger(Context context) {
            _context = context;
        }

        public void sendTimerFinishNotification() {
            int icon = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? R.mipmap.ic_launcher : R.drawable.methodegg;

            Notification.Builder builder =
                    new Notification.Builder(_context)
                            .setSmallIcon(icon)
                            .setContentTitle(_context.getString(R.string.timer))
                            .setContentText(_context.getString(R.string.ready))
                            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM))
                            .setAutoCancel(true);

            Intent resultIntent = new Intent(_context, NavigationActivity.class);
            resultIntent.putExtra(EXTRA_NOTIFICATION_TIMER, true);
            PendingIntent resultPendingIntent = PendingIntent.getActivity(
                    _context,
                    0,
                    resultIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            builder.setContentIntent(resultPendingIntent);


            NotificationManager notificationManager = (NotificationManager) _context.getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(TIMER_NOTIFICATION_ID, builder.getNotification());

        }
    }

Upvotes: 0

Views: 809

Answers (1)

Tmarsh2
Tmarsh2

Reputation: 417

Managed to find an answer, although Android documentation seems to believe this solution should be used only as a 'last resort'. I put

android {
    testOptions {
        unitTests.returnDefaultValues = true
    }
}

in the top level build.gradle.

According to documentation, this should be used if 'If you run a test that calls an API from the Android SDK that you do not mock', which I find bizare, as i'm not getting a 'Method ... not mocked' error, I am getting a 'ClassNotFoundException'

Upvotes: 2

Related Questions