Skip to content

Commit fd9c957

Browse files
committed
Unit test setupContextListeners not completing
- Add unit test: initWithContext_setupContextListenersNotCompleted_doesNotProduceNPE to reproduce the NPE of `outcomeEventsController` in `init()`. - Shadow the `OneSignal.setupContextListeners()` method to simulate it not completing (thus not initializing the `outcomeEventsController`). - Add new shadow of OneSignal besides ShadowOneSignal named `ShadowOneSignalWithMockSetupContextListeners` so other unit tests using `ShadowOneSignal` don't have behavior changed - However, the `languageContext` initialization is needed or else it leads to a subsequent NPE for this property in `registerUserTask()`. - Change access of `languageContext` in OneSignal.java from private to package-private so it can be accessed in unit tests.
1 parent 04ea523 commit fd9c957

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

OneSignalSDK/onesignal/src/main/java/com/onesignal/OneSignal.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ static Activity getCurrentActivity() {
370370
private static String smsId = null;
371371
private static int subscribableStatus = Integer.MAX_VALUE;
372372

373-
private static LanguageContext languageContext = null;
373+
// changed from private to package-private for unit test access
374+
static LanguageContext languageContext = null;
374375

375376
static OSRemoteNotificationReceivedHandler remoteNotificationReceivedHandler;
376377
static OSNotificationWillShowInForegroundHandler notificationWillShowInForegroundHandler;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.onesignal;
2+
3+
import com.onesignal.language.LanguageContext;
4+
5+
import org.robolectric.annotation.Implementation;
6+
import org.robolectric.annotation.Implements;
7+
8+
/**
9+
* This shadow is added for the test initWithContext_setupContextListenersNotCompleted_doesNotProduceNPE
10+
* Changes the behavior of one method without affecting other unit tests using ShadowOneSignal
11+
*/
12+
@Implements(OneSignal.class)
13+
public class ShadowOneSignalWithMockSetupContextListeners {
14+
15+
/**
16+
* Simulates setupContextListeners() in initWithContext() not completing.
17+
* However, languageContext initialization is needed for later, so that is the only code kept
18+
*/
19+
@Implementation
20+
public static void setupContextListeners(boolean wasAppContextNull) {
21+
22+
// Do work here that should only happen once or at the start of a new lifecycle
23+
if (wasAppContextNull) {
24+
OneSignal.languageContext = new LanguageContext(OneSignal.getSharedPreferences());
25+
}
26+
}
27+
}

OneSignalSDK/unittest/src/test/java/com/test/onesignal/OneSignalInitializationIntegrationTestsRunner.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.onesignal.ShadowCustomTabsClient;
88
import com.onesignal.ShadowCustomTabsSession;
99
import com.onesignal.ShadowOSUtils;
10+
import com.onesignal.ShadowOneSignalWithMockSetupContextListeners;
1011
import com.onesignal.ShadowOneSignalRestClient;
1112
import com.onesignal.ShadowPushRegistratorFCM;
1213
import com.onesignal.StaticResetHelper;
@@ -88,6 +89,19 @@ public void setRequiresUserPrivacyConsent_withTrue_CalledFirst_DoesNOTCreatePlay
8889
RestClientAsserts.assertRemoteParamsWasTheOnlyNetworkCall();
8990
}
9091

92+
// This test reproduces https://github.com/OneSignal/OneSignal-Android-SDK/issues/1514
93+
@Test
94+
@Config(shadows = { ShadowOneSignalWithMockSetupContextListeners.class })
95+
public void initWithContext_setupContextListenersNotCompleted_doesNotProduceNPE() throws Exception {
96+
OneSignal.setAppId(APP_ID);
97+
98+
// call initWithContext() but don't complete setupContextListeners() via the Shadow class
99+
// this prevents the initialization of outcomeEventsController in setupContextListeners()
100+
helper_OneSignal_initWithAppContext();
101+
threadAndTaskWait();
102+
// we implicitly test that no exception is thrown
103+
}
104+
91105
@Test
92106
public void setRequiresUserPrivacyConsent_withFalseAndRemoteTrue_DoesNOTCreatePlayer() throws Exception {
93107
ShadowOneSignalRestClient.setRemoteParamsRequirePrivacyConsent(true);

0 commit comments

Comments
 (0)