Recently i worked on a project where i had to test a service, and id like to share with you all how to do so easily. The android docs explain this as well HERE but they forget to mention a few key points.

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.

Put test in the androidTest directory

@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.