FileDocCategorySizeDatePackage
ServiceTestCase.javaAPI DocAndroid 5.1 API13228Thu Mar 12 22:22:42 GMT 2015android.test

ServiceTestCase

public abstract class ServiceTestCase extends AndroidTestCase
This test case provides a framework in which you can test Service classes in a controlled environment. It provides basic support for the lifecycle of a Service, and hooks with which you can inject various dependencies and control the environment in which your Service is tested.

Developer Guides

For more information about application testing, read the Testing developer guide.

Lifecycle Support. A Service is accessed with a specific sequence of calls, as described in the Services document. In order to support the lifecycle of a Service, ServiceTestCase enforces this protocol:

  • The {@link #setUp()} method is called before each test method. The base implementation gets the system context. If you override setUp(), you must call super.setUp() as the first statement in your override.
  • The test case waits to call {@link android.app.Service#onCreate()} until one of your test methods calls {@link #startService} or {@link #bindService}. This gives you an opportunity to set up or adjust any additional framework or test logic before you test the running service.
  • When one of your test methods calls {@link #startService ServiceTestCase.startService()} or {@link #bindService ServiceTestCase.bindService()}, the test case calls {@link android.app.Service#onCreate() Service.onCreate()} and then calls either {@link android.app.Service#startService(Intent) Service.startService(Intent)} or {@link android.app.Service#bindService(Intent, ServiceConnection, int) Service.bindService(Intent, ServiceConnection, int)}, as appropriate. It also stores values needed to track and support the lifecycle.
  • After each test method finishes, the test case calls the {@link #tearDown} method. This method stops and destroys the service with the appropriate calls, depending on how the service was started. If you override tearDown(), your must call the super.tearDown() as the last statement in your override.

Dependency Injection. A service has two inherent dependencies, its {@link android.content.Context Context} and its associated {@link android.app.Application Application}. The ServiceTestCase framework allows you to inject modified, mock, or isolated replacements for these dependencies, and thus perform unit tests with controlled dependencies in an isolated environment.

By default, the test case is injected with a full system context and a generic {@link android.test.mock.MockApplication MockApplication} object. You can inject alternatives to either of these by invoking {@link AndroidTestCase#setContext(Context) setContext()} or {@link #setApplication setApplication()}. You must do this before calling startService() or bindService(). The test framework provides a number of alternatives for Context, including {@link android.test.mock.MockContext MockContext}, {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, {@link android.content.ContextWrapper ContextWrapper}, and {@link android.test.IsolatedContext}.

Fields Summary
Class
mServiceClass
private android.content.Context
mSystemContext
private android.app.Application
mApplication
private T
mService
private boolean
mServiceAttached
private boolean
mServiceCreated
private boolean
mServiceStarted
private boolean
mServiceBound
private android.content.Intent
mServiceIntent
private int
mServiceId
Constructors Summary
public ServiceTestCase(Class serviceClass)
Constructor

param
serviceClass The type of the service under test.

        mServiceClass = serviceClass;
    
Methods Summary
protected android.os.IBinderbindService(android.content.Intent intent)

Starts the service under test, in the same way as if it were started by {@link android.content.Context#bindService(Intent, ServiceConnection, int) Context.bindService(Intent, ServiceConnection, flags)} with an {@link android.content.Intent} that identifies a service.

Notice that the parameters are different. You do not provide a {@link android.content.ServiceConnection} object or the flags parameter. Instead, you only provide the Intent. The method returns an object whose type is a subclass of {@link android.os.IBinder}, or null if the method fails. An IBinder object refers to a communication channel between the application and the service. The flag is assumed to be {@link android.content.Context#BIND_AUTO_CREATE}.

See Designing a Remote Interface Using AIDL for more information about the communication channel object returned by this method.

Note: To be able to use bindService in a test, the service must implement getService() method. An example of this is in the ApiDemos sample application, in the LocalService demo.

param
intent An Intent object of the form expected by {@link android.content.Context#bindService}.
return
An object whose type is a subclass of IBinder, for making further calls into the service.

        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);

        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        // no extras are expected by unbind
        mServiceIntent = intent.cloneFilter();
        IBinder result = mService.onBind(intent);

        mServiceBound = true;
        return result;
    
public android.app.ApplicationgetApplication()
Returns the Application object in use by the service under test.

return
The application object.
see
#setApplication

        return mApplication;
    
public TgetService()

return
An instance of the service under test. This instance is created automatically when a test calls {@link #startService} or {@link #bindService}.


                               
       
        return mService;
    
public android.content.ContextgetSystemContext()
Returns the real system context that is saved by {@link #setUp()}. Use it to create mock or other types of context objects for the service under test.

return
A normal system context.

        return mSystemContext;
    
public voidsetApplication(android.app.Application application)
Sets the application that is used during the test. If you do not call this method, a new {@link android.test.mock.MockApplication MockApplication} object is used.

param
application The Application object that is used by the service under test.
see
#getApplication()

        mApplication = application;
    
protected voidsetUp()
Gets the current system context and stores it. Extend this method to do your own test initialization. If you do so, you must call super.setUp() as the first statement in your override. The method is called before each test method is executed.

        super.setUp();

        // get the real context, before the individual tests have a chance to muck with it
        mSystemContext = getContext();

    
protected voidsetupService()
Creates the service under test and attaches all injected dependencies (Context, Application) to it. This is called automatically by {@link #startService} or by {@link #bindService}. If you need to call {@link AndroidTestCase#setContext(Context) setContext()} or {@link #setApplication setApplication()}, do so before calling this method.

        mService = null;
        try {
            mService = mServiceClass.newInstance();
        } catch (Exception e) {
            assertNotNull(mService);
        }
        if (getApplication() == null) {
            setApplication(new MockApplication());
        }
        mService.attach(
                getContext(),
                null,               // ActivityThread not actually used in Service
                mServiceClass.getName(),
                null,               // token not needed when not talking with the activity manager
                getApplication(),
                null                // mocked services don't talk with the activity manager
                );

        assertNotNull(mService);

        mServiceId = new Random().nextInt();
        mServiceAttached = true;
    
protected voidshutdownService()
Makes the necessary calls to stop (or unbind) the service under test, and calls onDestroy(). Ordinarily this is called automatically (by {@link #tearDown}, but you can call it directly from your test in order to check for proper shutdown behavior.

        if (mServiceStarted) {
            mService.stopSelf();
            mServiceStarted = false;
        } else if (mServiceBound) {
            mService.onUnbind(mServiceIntent);
            mServiceBound = false;
        }
        if (mServiceCreated) {
            mService.onDestroy();
            mServiceCreated = false;
        }
    
protected voidstartService(android.content.Intent intent)
Starts the service under test, in the same way as if it were started by {@link android.content.Context#startService(Intent) Context.startService(Intent)} with an {@link android.content.Intent} that identifies a service. If you use this method to start the service, it is automatically stopped by {@link #tearDown}.

param
intent An Intent that identifies a service, of the same form as the Intent passed to {@link android.content.Context#startService(Intent) Context.startService(Intent)}.

        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);

        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        mService.onStartCommand(intent, 0, mServiceId);

        mServiceStarted = true;
    
protected voidtearDown()

Shuts down the service under test. Ensures all resources are cleaned up and garbage collected before moving on to the next test. This method is called after each test method.

Subclasses that override this method must call super.tearDown() as their last statement.

throws
Exception

        shutdownService();
        mService = null;

        // Scrub out members - protects against memory leaks in the case where someone
        // creates a non-static inner class (thus referencing the test case) and gives it to
        // someone else to hold onto
        scrubClass(ServiceTestCase.class);

        super.tearDown();
    
public voidtestServiceTestCaseSetUpProperly()
Tests that {@link #setupService()} runs correctly and issues an {@link junit.framework.Assert#assertNotNull(String, Object)} if it does. You can override this test method if you wish.

throws
Exception

        setupService();
        assertNotNull("service should be launched successfully", mService);