Skip to content

Commit

Permalink
Improved Notification Unit Tests (#947)
Browse files Browse the repository at this point in the history
* move all notification tests to consistent package

* Add some unit tests for GCM Message parsing

* parameterize

* more
  • Loading branch information
phil-lopreiato authored Mar 8, 2020
1 parent ac96cae commit b43e027
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.thebluealliance.androidclient.datafeed.MyTbaDatafeed;
import com.thebluealliance.androidclient.datafeed.status.TBAStatusController;
import com.thebluealliance.androidclient.di.components.DaggerNotificationComponent;
import com.thebluealliance.androidclient.di.components.NotificationComponent;
import com.thebluealliance.androidclient.eventbus.NotificationsUpdatedEvent;
import com.thebluealliance.androidclient.gcm.notifications.AllianceSelectionNotification;
import com.thebluealliance.androidclient.gcm.notifications.AwardsPostedNotification;
Expand Down Expand Up @@ -88,26 +87,22 @@ public class GCMMessageHandler extends JobIntentService implements FollowsChecke
@Inject AccountController mAccountController;
@Inject AppConfig mAppConfig;

private NotificationComponent mComponenet;

@Override
public void onCreate() {
super.onCreate();
getComponent();
mComponenet.inject(this);
inject();
}

private void getComponent() {
if (mComponenet == null) {
TbaAndroid application = ((TbaAndroid) getApplication());
mComponenet = DaggerNotificationComponent.builder()
.applicationComponent(application.getComponent())
.datafeedModule(application.getDatafeedModule())
.rendererModule(new RendererModule())
.authModule(application.getAuthModule())
.gcmModule(application.getGcmModule())
.build();
}
protected void inject() {
TbaAndroid application = ((TbaAndroid) getApplication());
DaggerNotificationComponent.builder()
.applicationComponent(application.getComponent())
.datafeedModule(application.getDatafeedModule())
.rendererModule(new RendererModule())
.authModule(application.getAuthModule())
.gcmModule(application.getGcmModule())
.build()
.inject(this);
}

@Override
Expand All @@ -133,7 +128,7 @@ public static void enqueueWork(Context context, Intent work) {
}

@Override
protected void onHandleWork(Intent intent) {
public void onHandleWork(Intent intent) {
Bundle extras = intent.getExtras();
if (extras == null) {
TbaLogger.w("Intent with no extras!");
Expand Down Expand Up @@ -205,13 +200,18 @@ public void handleMessage(Context c, String messageType, String messageData) {
break;
}

if (notification == null) return;
if (notification == null) {
TbaLogger.w("Unknown notification for type " + messageType);
return;
}

TbaLogger.d("Notification type picked");

try {
notification.parseMessageData();
TbaLogger.d("JSON Data parsed");
} catch (JsonParseException e) {
TbaLogger.e("Error parsing incoming message json");
e.printStackTrace();
TbaLogger.e("Error parsing incoming message json", e);
return;
}

Expand All @@ -220,7 +220,10 @@ public void handleMessage(Context c, String messageType, String messageData) {
Notification built;

built = notification.buildNotification(c, this);
if (built == null) return;
if (built == null) {
TbaLogger.d("Unable to build notification type " + messageType);
return;
}

/* Update the data coming from this notification in the local db */
notification.updateDataLocally();
Expand Down Expand Up @@ -252,6 +255,8 @@ public void handleMessage(Context c, String messageType, String messageData) {

notify(c, notification, built);
}
} else {
TbaLogger.d("Notification type " + messageType + " disabled by config");
}
} catch (Exception e) {
// We probably tried to post a null notification or something like that. Oops...
Expand All @@ -264,6 +269,7 @@ private void notify(Context c, BaseNotification notification, Notification built
int id = STACK_NOTIFICATIONS ? notification.getNotificationId() : SINGULAR_NOTIFICATION_ID;

setNotificationParams(built, c, notification.getNotificationType(), mPrefs);
TbaLogger.i(("Notifying: " + id));
notificationManager.notify(id, built);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import com.thebluealliance.androidclient.database.tables.DistrictsTable;
import com.thebluealliance.androidclient.database.tables.EventTeamsTable;
import com.thebluealliance.androidclient.database.tables.EventsTable;
import com.thebluealliance.androidclient.database.tables.FavoritesTable;
import com.thebluealliance.androidclient.database.tables.MatchesTable;
import com.thebluealliance.androidclient.database.tables.MediasTable;
import com.thebluealliance.androidclient.database.tables.NotificationsTable;
import com.thebluealliance.androidclient.database.tables.SubscriptionsTable;
import com.thebluealliance.androidclient.database.tables.TeamsTable;
import com.thebluealliance.androidclient.datafeed.HttpModule;

Expand Down Expand Up @@ -96,4 +98,20 @@ public static MediasTable mockMediasTable(Database database) {
return table;
}

public static FavoritesTable mockFavoritesTable(Database database) {
SQLiteDatabase db = mock(SQLiteDatabase.class);
FavoritesTable table = new FavoritesTable(db);
when(database.getFavoritesTable()).thenReturn(table);
when(database.getWritableDatabase()).thenReturn(db);
return table;
}

public static SubscriptionsTable mockSubscriptionsTable(Database database) {
SQLiteDatabase db = mock(SQLiteDatabase.class);
SubscriptionsTable table = new SubscriptionsTable(db);
when(database.getSubscriptionsTable()).thenReturn(table);
when(database.getWritableDatabase()).thenReturn(db);
return table;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.thebluealliance.androidclient.di;

import com.thebluealliance.androidclient.gcm.GCMMessageHandlerWithMocks;

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(
modules = {MockGceModule.class, MockRendererModule.class, MockConfigModule.class, MockGcmModule.class, MockAccountModule.class, MockAuthModule.class},
dependencies = MockApplicationComponent.class)
public interface MockNotificationComponent {
void inject(GCMMessageHandlerWithMocks handlerWithMocks);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@

import javax.inject.Singleton;

import androidx.test.core.app.ApplicationProvider;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;

import static org.mockito.Mockito.spy;

@Module
public class MockTbaAndroidModule {
public class MockTbaAndroidModule {

@Provides
@Singleton
Expand All @@ -57,7 +58,7 @@ public Database provideDatabase() {
@Provides
@Singleton
public SharedPreferences provideSharedPrefs(Context context) {
return Mockito.mock(SharedPreferences.class);
return ApplicationProvider.getApplicationContext().getSharedPreferences("prefs", 0);
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.thebluealliance.androidclient.gcm;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;

import com.google.gson.JsonObject;
import com.thebluealliance.androidclient.datafeed.framework.ModelMaker;
import com.thebluealliance.androidclient.gcm.notifications.BaseNotification;
import com.thebluealliance.androidclient.gcm.notifications.NotificationTypes;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.Robolectric;
import org.robolectric.Shadows;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import androidx.test.core.app.ApplicationProvider;

import static org.junit.Assert.assertEquals;

@RunWith(Enclosed.class)
public class GCMMessageHandlerTest {

@RunWith(ParameterizedRobolectricTestRunner.class)
public static class TestRenderSingleNotifications {

private NotificationManager mNotificationManager;

@ParameterizedRobolectricTestRunner.Parameter(0)
public String mNotificationType;
@ParameterizedRobolectricTestRunner.Parameter(1)
public String mNotificationDataFileName;
@ParameterizedRobolectricTestRunner.Parameter(2)
public int mExpectedPriority;

@Before
public void setUp() {
Context applicationContext = ApplicationProvider.getApplicationContext();
mNotificationManager = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
}

@ParameterizedRobolectricTestRunner.Parameters(name = "NotificationType = {0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{NotificationTypes.ALLIANCE_SELECTION, "notification_alliance_selection", Notification.PRIORITY_HIGH},
{NotificationTypes.AWARDS, "notification_awards_posted", Notification.PRIORITY_HIGH},
{NotificationTypes.DISTRICT_POINTS_UPDATED, "notification_district_points_updated", Notification.PRIORITY_HIGH},
{NotificationTypes.EVENT_DOWN, "notification_event_down", Notification.PRIORITY_HIGH},
{NotificationTypes.LEVEL_STARTING, "notification_level_starting", Notification.PRIORITY_HIGH},
{NotificationTypes.MATCH_SCORE, "notification_match_score", Notification.PRIORITY_HIGH},
{NotificationTypes.PING, "notification_ping", Notification.PRIORITY_LOW},
{NotificationTypes.SCHEDULE_UPDATED, "notification_schedule_updated", Notification.PRIORITY_HIGH},
{NotificationTypes.UPCOMING_MATCH, "notification_upcoming_match", Notification.PRIORITY_HIGH},
});
}

@Test
public void testPostSingleNotification() {
Intent intent = buildIntent(mNotificationType, mNotificationDataFileName);
GCMMessageHandlerWithMocks service = Robolectric.setupService(GCMMessageHandlerWithMocks.class);
service.onCreate();
service.onHandleWork(intent);

List<Notification> notifications = Shadows.shadowOf(mNotificationManager).getAllNotifications();
assertEquals(1, notifications.size());

Notification notification = notifications.get(0);
assertEquals(BaseNotification.NOTIFICATION_CHANNEL, notification.getChannelId());
assertEquals(mExpectedPriority, notification.priority);
}
}

private static Intent buildIntent(String notificationType, String dataFileName) {
JsonObject notificationData = ModelMaker.getModel(JsonObject.class, dataFileName);
Intent intent = new Intent("com.google.android.c2dm.intent.RECEIVE");
intent.putExtra("notification_type", notificationType);
intent.putExtra("message_data", notificationData.toString());
return intent;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.thebluealliance.androidclient.gcm;

import com.thebluealliance.androidclient.TestTbaAndroid;
import com.thebluealliance.androidclient.database.DatabaseMocker;
import com.thebluealliance.androidclient.di.DaggerMockNotificationComponent;
import com.thebluealliance.androidclient.di.MockRendererModule;

public class GCMMessageHandlerWithMocks extends GCMMessageHandler {

/*
* A version of the service that does its DI using mocks
*/

@Override
protected void inject() {
TestTbaAndroid application = ((TestTbaAndroid) getApplication());
DaggerMockNotificationComponent.builder()
.mockApplicationComponent(application.getMockComponent())
.mockDatafeedModule(application.getMockDatafeedModule())
.mockRendererModule(new MockRendererModule())
.mockAuthModule(application.getMockAuthModule())
.mockGcmModule(application.getMockGcmModule())
.build()
.inject(this);
initMocks();
}

public void initMocks() {
DatabaseMocker.mockMatchesTable(mDb);
DatabaseMocker.mockEventsTable(mDb);
DatabaseMocker.mockAwardsTable(mDb);
DatabaseMocker.mockFavoritesTable(mDb);
DatabaseMocker.mockSubscriptionsTable(mDb);
DatabaseMocker.mockNotificationsTable(mDb);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.thebluealliance.androidclient.notifications;
package com.thebluealliance.androidclient.gcm.notifications;

import android.app.Notification;
import android.content.Context;
Expand All @@ -11,8 +11,6 @@
import com.thebluealliance.androidclient.adapters.ViewEventFragmentPagerAdapter;
import com.thebluealliance.androidclient.database.writers.EventWriter;
import com.thebluealliance.androidclient.datafeed.framework.ModelMaker;
import com.thebluealliance.androidclient.gcm.notifications.AllianceSelectionNotification;
import com.thebluealliance.androidclient.gcm.notifications.NotificationTypes;
import com.thebluealliance.androidclient.helpers.MyTBAHelper;
import com.thebluealliance.androidclient.models.Event;
import com.thebluealliance.androidclient.models.StoredNotification;
Expand All @@ -35,8 +33,10 @@
@RunWith(AndroidJUnit4.class)
public class AllianceSelectionNotificationTest {

@Mock private Context mContext;
@Mock private EventWriter mWriter;
@Mock
private Context mContext;
@Mock
private EventWriter mWriter;
private AllianceSelectionNotification mNotification;
private JsonObject mData;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.thebluealliance.androidclient.notifications;
package com.thebluealliance.androidclient.gcm.notifications;

import android.app.Notification;
import android.content.Context;
Expand All @@ -11,8 +11,6 @@
import com.thebluealliance.androidclient.adapters.ViewEventFragmentPagerAdapter;
import com.thebluealliance.androidclient.database.writers.AwardListWriter;
import com.thebluealliance.androidclient.datafeed.framework.ModelMaker;
import com.thebluealliance.androidclient.gcm.notifications.AwardsPostedNotification;
import com.thebluealliance.androidclient.gcm.notifications.NotificationTypes;
import com.thebluealliance.androidclient.helpers.MyTBAHelper;
import com.thebluealliance.androidclient.models.Award;
import com.thebluealliance.androidclient.models.StoredNotification;
Expand All @@ -37,8 +35,10 @@
@RunWith(AndroidJUnit4.class)
public class AwardsPostedNotificationTest {

@Mock private Context mContext;
@Mock private AwardListWriter mWriter;
@Mock
private Context mContext;
@Mock
private AwardListWriter mWriter;
private AwardsPostedNotification mNotification;
private JsonObject mData;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.thebluealliance.androidclient.notifications;
package com.thebluealliance.androidclient.gcm.notifications;

import android.app.Notification;
import android.content.Context;
Expand All @@ -10,8 +10,6 @@
import com.thebluealliance.androidclient.activities.ViewEventActivity;
import com.thebluealliance.androidclient.adapters.ViewEventFragmentPagerAdapter;
import com.thebluealliance.androidclient.datafeed.framework.ModelMaker;
import com.thebluealliance.androidclient.gcm.notifications.CompLevelStartingNotification;
import com.thebluealliance.androidclient.gcm.notifications.NotificationTypes;
import com.thebluealliance.androidclient.helpers.MyTBAHelper;
import com.thebluealliance.androidclient.models.StoredNotification;

Expand Down
Loading

0 comments on commit b43e027

Please sign in to comment.