Mocking Bound Services on Android

Let’s suppose we have a Fragment that we want to unit test.
However, let’s also suppose that this fragment binds to/unbinds from a service through its lifecycle callback (onStart(), onStop()).

The main advantage of Bound Service  is that the latter lives only if at least one client is bound to it. By binding to/unbinding from a Service through a Fragment or Activity’s lifecycle, we are in full control of the existence of that Service and triggers it only when the user needs it.

To use a bound service, you mainly need 2 classes : an Android Service and a ServiceConnection that monitors the state of the service connection (Service connected/disconnected).

Below a very simple Service and ServiceConnection :

 

As you can see, as soon as the service is created, an expensive task is triggered within the onCreate() callback.

To bind to the service, we will make proper use of the ServiceConnector within our Fragment’s life cycle :

The Unit Test

As we have already seen, as soon as the service is created, an expensive task is triggered within the onCreate() callback. This could lead to pollute and add uncertainty to the result of our unit test (such as the IBinder being null within the onServiceConnected() callback). Just to remind you, a good unit test should be consistent, which means that it should always return the same result for the same test.

So in order not to be disrupted by the Service, we are goind to mock not only the Service, but also stub the IBinder. Thus, anytime a client (the fragment in our case) wants to bind to the Service, it will receive a stub IBinder that will return a mock Service.
Let’s have a look to the Unit Test (we will use Robolectric and Mockito to do so ) and specifically to the mockBoundLocalService() method:

The Robolectric’s ShadowApplication object has a method called setComponentNameAndServiceForBindService() that allows to set a IBinder for the given Service ComponentName. Using this setter, we are able to pass a stub IBinder within the onServiceConnected() callback whenever a client tries to bind to our service.

 

2 réflexions au sujet de « Mocking Bound Services on Android »

  1. Veeren Mandalia dit :

    FYI, I believe you should be making a unbindService call for each bindService call, regardless of whether onServiceConnected/onServiceDisconnected has been called. Think an Android example is incorrect on their website.

    • Hi @veerenmandalia:disqus, I haven’t checked this yet, so I can’t confirmed it. Could you please share some pointers or source code link that highlights this point ? Cheers

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *