The project i was working on was to initialize an SDK from a third party app, when the SDK was initialized, by the time all of the initialization was complete, there were 2 services that should’ve been started properly.
Here is how i tested this without using the approach mentioned in the google documentation mentioned above.
After the SDK was initiated, inside of init method a few things occurred and one of them was to call into the starServices method.
public class TheSDK {
private static void init(@NonNull final Context context) {
// .....
startServices(context);
// .....
}
private static void startServices(final @NonNull Context context) {
context.startService(new Intent(context, Service1.class));
context.startService(new Intent(context, service2.class));
}
public static class Builder {
// .....
public void init() {
TheSDK.init(...);
}
}
}
As you can see above 2 services were stared. I will only show the test for one of them since it is the same thing for both.
Here is what the service looks like…
public class Service1 extends Service {
@RestrictTo (RestrictTo.Scope.TESTS)
static boolean started;
private SomeBroadCastReceiver receiver;
public Service1() {
}
@Override
public IBinder onBind(Intent intent) {
throw null;
}
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
started = true;
//...init broadcast receiver and whatnot
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}
The most important part in this whole receiver is this:
@RestrictTo (RestrictTo.Scope.TESTS)
static boolean started;
and in this line inside the onCreate
started = true;
These 3 lines are very straight forward. A variable is created to represent if the service was started or not, and it is set to true in the Service onCreate method. The line above the “started” boolean declaration tells us that the boolean is restricted to TESTS only. Production code should not use this.
The test is even easier. First of all make sure that your test is an android test. Meaning put it under androidTest instead of test.
@RunWith (AndroidJUnit4.class) // <<----Make sure you add this!!!!
public class TheSDKTest {
@Test
public void test_services_started_on_init() throws TimeoutException {
final Context context = InstrumentationRegistry.getTargetContext();
new TheSDK.Builder(context").init();
assertTrue(Service1.started);
assertTrue(Service2.started);
}
}
Note: Make sure you add @RunWith (AndroidJUnit4.class) above the test class.
How easy was that?!
Oh and BTW, these test run on your devices, you will need a device connected in order to run the test. These tests are called instrumentation tests. Instrumentation tests require the Android OS (to run on a phone or emulator). Whereas a unit test just runs on the JVM/local on your IDE.
Note: nowhere in this post did i mention to add the services to the manifest, so make sure that the services are added to the manifest accordingly.